{"id":37016845,"url":"https://github.com/getkyo/kyo","last_synced_at":"2026-01-14T01:55:17.023Z","repository":{"id":64100873,"uuid":"467635354","full_name":"getkyo/kyo","owner":"getkyo","description":"Toolkit for Scala Development","archived":false,"fork":false,"pushed_at":"2025-12-22T19:48:32.000Z","size":12817,"stargazers_count":745,"open_issues_count":81,"forks_count":83,"subscribers_count":27,"default_branch":"main","last_synced_at":"2025-12-27T04:21:43.334Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://getkyo.io","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/getkyo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-03-08T18:44:26.000Z","updated_at":"2025-12-23T00:45:30.000Z","dependencies_parsed_at":"2023-09-24T08:37:26.006Z","dependency_job_id":"4a2ac514-8044-4ec2-9720-e18c8dfad718","html_url":"https://github.com/getkyo/kyo","commit_stats":{"total_commits":1789,"total_committers":27,"mean_commits":66.25925925925925,"dds":0.2945779765231973,"last_synced_commit":"3a76512928ab90a8ad02f652ae78488ec7d2ee93"},"previous_names":["fwbrasil/kyo"],"tags_count":92,"template":false,"template_full_name":null,"purl":"pkg:github/getkyo/kyo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getkyo%2Fkyo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getkyo%2Fkyo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getkyo%2Fkyo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getkyo%2Fkyo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/getkyo","download_url":"https://codeload.github.com/getkyo/kyo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getkyo%2Fkyo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T00:40:43.272Z","status":"ssl_error","status_checked_at":"2026-01-14T00:40:42.636Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T01:55:16.161Z","updated_at":"2026-01-14T01:55:17.011Z","avatar_url":"https://github.com/getkyo.png","language":"Scala","readme":"### Please visit https://getkyo.io for an indexed version of this documentation.\n##\n\n\u003cimg src=\"https://raw.githubusercontent.com/getkyo/kyo/master/kyo.png\" width=\"200\" alt=\"Kyo\"\u003e\n\n## Introduction\n\n[![Build Status](https://github.com/getkyo/kyo/workflows/build/badge.svg)](https://github.com/getkyo/kyo/actions)\n[![Discord](https://img.shields.io/discord/1087005439859904574)](https://discord.gg/KxxkBbW8bq)\n[![Version](https://img.shields.io/maven-central/v/io.getkyo/kyo-core_3)](https://search.maven.org/search?q=g:io.getkyo)\n[![javadoc](https://javadoc.io/badge2/io.getkyo/kyo-core_3/javadoc.svg)](https://javadoc.io/doc/io.getkyo/kyo-core_3)\n\nKyo is a powerful toolkit for Scala development, providing a rich standard library for development across Native, JVM, and JavaScript platforms.\nKyo introduces a novel approach based on algebraic effects to deliver straightforward APIs in the pure Functional Programming paradigm.\n\nKyo achieves this without requiring a pretext of concepts from category theory, and avoiding cryptic operators. This results in a development experience that is both intuitive and robust.\n\nIts effect system builds on a simple yet powerful abstraction: algebraic effects with modular handlers. Unlike systems that rely on a fixed set of effect channels, typically limited to error and environment, Kyo allows developers to define and compose an open set of effects tailored to their specific needs. This enables more precise and granular control over computational context, without unnecessary complexity.\n\n## [Kyo: A New Approach to Functional Effects in Scala](https://www.youtube.com/watch?v=uA2_TWP5WF4)\n\n\u003e This podcast gives a well rounded overview of Kyo, including live coding!\n\n\u003ca href=\"http://www.youtube.com/watch?v=uA2_TWP5WF4\" title=\"Kyo: A New Approach to Functional Effects in Scala\"\u003e\n    \u003cimg src=\"https://img.youtube.com/vi/uA2_TWP5WF4/maxresdefault.jpg\" alt=\"Kyo: A New Approach to Functional Effects in Scala\" width=\"500\" height=\"300\"\u003e\n\u003c/a\u003e\n\n### Getting Started\n\nKyo is structured as a monorepo, published to Maven Central:\n\n#### Core Libraries\n\n| Module          | JVM | JS  | Native | Description                                                   |\n| --------------- | --- | --- | ------ | ------------------------------------------------------------- |\n| kyo-data        | ✅   | ✅   | ✅      | Efficient `Maybe`, `Result`, `Duration`, and other data types |\n| kyo-kernel      | ✅   | ✅   | ✅      | Core algebraic effects engine and type-level effect tracking  |\n| kyo-prelude     | ✅   | ✅   | ✅      | Pure effects: `Abort`, `Env`, `Var`, `Emit`, `Choice`, etc.   |\n| kyo-parse       | ✅   | ✅   | ✅      | Effects for parsing                                           |\n| kyo-core        | ✅   | ✅   | ✅      | Side-effectful computations: `Sync`, `Async`, `Scope`, etc.   |\n| kyo-direct      | ✅   | ✅   | ✅      | Direct-style syntax using `.await` and control flow           |\n| kyo-combinators | ✅   | ✅   | ✅      | ZIO-like effect combinators and utility methods               |\n| kyo-actor       | ✅   | ✅   | ✅      | Type-safe actor system with supervision and messaging         |\n| kyo-stm         | ✅   | ✅   | ✅      | Software transactional memory for managing state              |\n| kyo-offheap     | ✅   | ❌   | ✅      | Direct memory allocation and off-heap data structures         |\n\n#### Integrations\n\n| Module               | JVM | JS  | Native | Description                                                          |\n| -------------------- | --- | --- | ------ | -------------------------------------------------------------------- |\n| kyo-sttp             | ✅   | ✅   | ✅      | HTTP client using Sttp with automatic effect management              |\n| kyo-tapir            | ✅   | ❌   | ❌      | HTTP server endpoints using Tapir with Netty backend                 |\n| kyo-caliban          | ✅   | ❌   | ❌      | GraphQL server using Caliban with schema derivation                  |\n| kyo-zio              | ✅   | ✅   | ❌      | Bidirectional ZIO interop with support for ZIO, ZLayer, and ZStream  |\n| kyo-zio-test         | ✅   | ✅   | ❌      | ZIO Test framework integration for testing Kyo effects               |\n| kyo-cats             | ✅   | ✅   | ❌      | Bidirectional Cats IO interop with support for Sync, Async and Abort |\n| kyo-cache            | ✅   | ❌   | ❌      | High-performance caching using Caffeine with memoization             |\n| kyo-stats-registry   | ✅   | ✅   | ✅      | Metrics collection with counters, histograms, and gauges             |\n| kyo-stats-otel       | ✅   | ❌   | ❌      | OpenTelemetry integration for metrics and tracing export             |\n| kyo-playwright       | ✅   | ❌   | ❌      | Browser automation testing using Microsoft Playwright                |\n| kyo-reactive-streams | ✅   | ❌   | ❌      | Bidirectional Reactive Streams interop implementation                |\n| kyo-aeron            | ✅   | ❌   | ❌      | High-performance messaging using Aeron transport                     |\n\n#### Scheduler\n\n\u003e These modules are designed to be used independently, without requiring the Kyo effect system. These modules provide specific functionalities that can be integrated into any Scala project, regardless of whether it uses Kyo's effect system or not. They are also compiled with support for Scala 2, enabling adoption without needing to update to Scala 3.\n\n| Module                | JVM | JS  | Native | Description                                                 |\n| --------------------- | --- | --- | ------ | ----------------------------------------------------------- |\n| kyo-scheduler         | ✅   | ✅   | ✅      | Adaptive work-stealing scheduler with automatic parallelism |\n| kyo-scheduler-cats    | ✅   | ❌   | ❌      | Drop-in Cats Effect `IORuntime` replacement                 |\n| kyo-scheduler-finagle | ✅   | ❌   | ❌      | Twitter Finagle integration for improved performance        |\n| kyo-scheduler-pekko   | ✅   | ❌   | ❌      | Apache Pekko actor system integration                       |\n| kyo-scheduler-zio     | ✅   | ❌   | ❌      | ZIO `Runtime` implementation for better ZIO performance     |\n\n\nKyo's scheduler is designed to function as a global pool with automatic sizing. It can reduce the overhead of multiple thread pools, which can be problematic due to CPU throttling.\n\nAdd Kyo modules to your `build.sbt`:\n\n```sbt\nlibraryDependencies += \"io.getkyo\" %% \"kyo-prelude\" % \"\u003cversion\u003e\"\nlibraryDependencies += \"io.getkyo\" %% \"kyo-core\"    % \"\u003cversion\u003e\"\n```\n\nUse `%%` for JVM/Scala Native, or `%%%` for ScalaJS cross-compilation. See the module tables above for platform support. Replace `\u003cversion\u003e` with: ![Version](https://img.shields.io/maven-central/v/io.getkyo/kyo-core_3)\n\n\n## Talks\n\u003e These talks are listed in reverse chronological order, as Kyo has grown and transformed significantly in preparation for 1.0.\n\n| Title                                                                                                          | Speaker(s)                 | Host                   | Date           | Resources                                                                                             |\n| -------------------------------------------------------------------------------------------------------------- | -------------------------- | ---------------------- | -------------- | ----------------------------------------------------------------------------------------------------- |\n| [Suspension: the magic behind composability (or \"The Kyo Monad\")](https://www.youtube.com/watch?v=y3KiuFczOFE) | Flavio Brasil              | Lambda Days            | June, 2025     | [Slides](https://speakerdeck.com/fwbrasil/suspension-the-magic-behind-composability-or-the-kyo-monad) |\n| [An Algebra of Thoughts: When Kyo effects meet LLMs](https://www.youtube.com/watch?v=KIjtXM5dlgY)              | Flavio Brasil              | Func Prog Sweden       | May, 2025      | [Slides](https://www.canva.com/design/DAGoBBQ3oJw/vFGuHA0z_ZFtZgbJQbQHXw/view?utlId=h3b4db70b27#540)  |                                                                                                   |\n| [Redefining Stream Composition with Algebraic Effects](https://www.youtube.com/watch?v=WcYKTyQwEA0)            | Adam Hearn                 | LambdaConf             | May, 2025      |                                                                                                       |\n| [Kyo: A New Approach to Functional Effects in Scala](https://www.youtube.com/watch?v=uA2_TWP5WF4)              | Flavio Brasil \u0026 Adam Hearn | Scala for Fun \u0026 Profit | February, 2025 |                                                                                                       |\n| [The Actor Model Beyond Akka With Kyo](https://www.youtube.com/watch?v=VU31k3lQ8yU)                            | Damian Reeves              | Functional Scala       | December, 2024 |                                                                                                       |\n| [Building Robust Applications with Kyo: A Hands on Introduction](https://www.youtube.com/watch?v=QW8mAJr0Wso)  | Adam Hearn                 | ScalaIO                | November, 2024 | [Workshop + Slides](https://github.com/hearnadam/kyo-workshop)                                        |\n| [Comparing Approaches to Structured Concurrency](https://www.youtube.com/watch?v=g6dyLhAublQ)                  | James Ward \u0026 Adam Hearn    | LambdaConf             | May, 2024      |                                                                                                       |\n| [Algebraic Effects from Scratch](https://www.youtube.com/watch?v=qPvPdRbTF-E)                                 | Kit Langton                | Func Prog Sweden       | April, 2024     |                                                                                                       |\n| [Releasing Kyo: When Performance Meets Elegance In Scala](https://www.youtube.com/watch?v=FXkYKQRC9LI)         | Flavio Brasil              | Functional Scala       | December, 2023 |                                                                                                       |\n\n\n## IDE Support\n\nKyo uses advanced features from the latest Scala 3 versions that [IntelliJ IDEA may not fully support](https://github.com/getkyo/kyo/issues/1249). For a smoother development experience, we recommend using a [Metals-based](https://scalameta.org/metals/) IDE with the SBT BSP server, which offers better stability. Refer to the Metals [guide](https://scalameta.org/metals/docs/build-tools/sbt/#sbt-build-server) to switch from Bloop to SBT BSP.\n\n## Recommended Compiler Flags\n\nWe strongly recommend enabling these Scala compiler flags when working with Kyo to catch common mistakes and ensure proper effect handling:\n\n1. `-Wvalue-discard`: Warns when non-Unit expression results are unused.\n2. `-Wnonunit-statement`: Warns when non-Unit expressions are used in statement position.\n3. `-Wconf:msg=(unused.*value|discarded.*value|pure.*statement):error`: Elevates the warnings from the previous flags to compilation errors.\n4. `-language:strictEquality`: Enforces type-safe equality comparisons by requiring explicit evidence that types can be safely compared.\n\nAdd these to your `build.sbt`:\n\n```scala \nscalacOptions ++= Seq(\n    \"-Wvalue-discard\", \n    \"-Wnonunit-statement\", \n    \"-Wconf:msg=(unused.*value|discarded.*value|pure.*statement):error\",\n    \"-language:strictEquality\"\n)\n```\n\nThese flags help catch three common issues in Kyo applications:\n\n1. **A pure expression does nothing in statement position**: Often suggests that a Kyo computation is being discarded and will never execute, though it can also occur with other pure expressions. Common fixes include using `map` to chain transformations or explicitly handling the result.\n\n2. **Unused/Discarded non-Unit value**: Most commonly occurs when you pass a computation to a method that can only handle some of the effects that your computation requires. For example, passing a computation that needs both `Sync` and `Abort[Exception]` effects as a method parameter that only accepts `Sync` can trigger this warning. While this warning can appear in other scenarios (like ignoring any non-Unit value), in Kyo applications it typically signals that you're trying to use a computation in a context that doesn't support all of its required effects.\n\n3. **Values cannot be compared with == or !=**: The strict equality flag ensures type-safe equality comparisons by requiring that compared types are compatible. This is particularly important for Kyo's opaque types like `Maybe`, where comparing values of different types could lead to inconsistent behavior. The flag helps catch these issues at compile-time, ensuring you only compare values that can be meaningfully compared. For example, you cannot accidentally compare a `Maybe[Int]` with an `Option[Int]` or a raw `Int`, preventing subtle bugs. To disable the check for a specific scope, introduce an unsafe evidence: `given [A, B]: CanEqual[A, B] = CanEqual.derived`\n\n\u003e Note: You may want to selectively disable these warnings in test code, where it's common to assert side effects without using their returned values: `Test / scalacOptions --= Seq(options, to, disable)`\n\n### The \"Pending\" type: `\u003c`\n\nIn Kyo, computations are expressed via the infix type `\u003c`, known as \"Pending\". It takes two type parameters:\n\n```scala \nopaque type \u003c[+A, -S]\n```\n\n1. `A` - The type of the expected output.\n2. `S` - The pending effects that need to be handled. Effects are represented by an unordered type-level set via a type intersection.\n\n```scala \nimport kyo.*\n\n// 'Int' pending 'Abort[Absent]'\n// 'Absent' is Kyo's equivalent of 'None' via the 'Maybe' type\nInt \u003c Abort[Absent]\n\n// 'String' pending 'Abort[Absent]' and 'Sync'\nString \u003c (Abort[Absent] \u0026 Sync)\n```\n\nAny type `T` is automatically considered to be of type `T \u003c Any`, where `Any` denotes an empty set of pending effects. In simpler terms, this means that every value in Kyo is automatically a computation, but one without any effects that you need to explicitly handle.\n\nThis design choice streamlines your code by removing the necessity to differentiate between pure values and computations that may have effects. So, when you're dealing with a value of type `T \u003c Any`, you can safely `eval` the pure value directly, without worrying about handling any effects.\n\n```scala\nimport kyo.*\n\n// An 'Int' is also an 'Int \u003c Any'\nval a: Int \u003c Any = 1\n\n// Since there are no pending effects,\n// the computation can produce a pure value\nval b: Int = a.eval\n```\n\n\u003e Note: This README provides explicit type declarations for clarity. However, Scala's type inference is generally able to infer Kyo types properly.\n\nThis unique property removes the need to juggle between `map` and `flatMap`. All values are automatically promoted to a Kyo computation with zero pending effects, enabling you to focus on your application logic rather than the intricacies of effect handling.\n\n```scala\nimport kyo.*\n\n// Kyo still supports both `map`\n// and `flatMap`.\ndef example1(\n    a: Int \u003c Sync,\n    b: Int \u003c Abort[Exception]\n): Int \u003c (Sync \u0026 Abort[Exception]) =\n    a.flatMap(v =\u003e b.map(_ + v))\n\n// But using only `map` is recommended\n// since it functions like `flatMap` due\n// to effect widening.\ndef example2(\n    a: Int \u003c Sync,\n    b: Int \u003c Abort[Exception]\n): Int \u003c (Sync \u0026 Abort[Exception]) =\n    a.map(v =\u003e b.map(_ + v))\n```\n\nThe `map` method automatically updates the set of pending effects. When you apply `map` to computations that have different pending effects, Kyo reconciles these into a new computation type that combines all the unique pending effects from both operands.\n\nKyo also offers an `andThen` method for more fluent code, combining two computations, discarding the result of the first one.\n\n```scala\nimport kyo.*\n\nval a: Unit \u003c Sync =\n    Sync.defer(println(\"hello\"))\n\nval b: String \u003c Sync =\n    a.andThen(\"test\")\n```\n\nThe `handle` method allows for chaining effect handlers without nesting parentheses. It's particularly useful when dealing with multiple effects.\n\n```scala\nimport kyo.*\n\nval a: Int \u003c (Abort[String] \u0026 Env[Int]) =\n    for\n        v \u003c- Abort.get(Right(42))\n        e \u003c- Env.get[Int]\n    yield v + e\n\n// Handle effects using `handle`\nval b: Result[String, Int] =\n    a.handle(Abort.run(_))   // Handle Abort\n     .handle(Env.run(10))    // Handle Env\n     .eval                 // Evaluate the computation\n\n// Equivalent without `handle`\nval c: Result[String, Int] =\n    Env.run(10)(Abort.run(a)).eval\n\n// `handle` also supports multiple functions\nval d: Result[String, Int] =\n    a.handle(Abort.run(_), Env.run(10)).eval\n\n// Mixing effect handling, 'map' transformation, and 'eval'\nval e: Int =\n    a.handle(\n        Abort.run(_),\n        Env.run(10),\n        _.map(_.getOrElse(24)), // Convert Result to Int\n        _.eval\n    )\n```\n\n### Effect widening\n\nKyo's set of pending effects is a contravariant type parameter. This encoding permits computations to be widened to encompass a larger set of effects.\n\n```scala\nimport kyo.*\n\n// An 'Int' with an empty effect set (`Any`)\nval a: Int \u003c Any =\n    1\n\n// Widening the effect set from empty (`Any`)\n// to include `Sync`\nval b: Int \u003c Sync =\n    a\n\n// Further widening the effect set to include\n// both `Sync` and `Abort[Exception]`\nval c: Int \u003c (Sync \u0026 Abort[Exception]) =\n    b\n\n// Directly widening a pure value to have\n// `Sync` and `Abort[Exception]`\nval d: Int \u003c (Sync \u0026 Abort[Exception]) =\n    42\n```\n\nThis characteristic enables a fluent API for effectful code. Methods can accept parameters with a specific set of pending effects while also permitting those with fewer or no effects.\n\n```scala\nimport kyo.*\n\n// The function expects a parameter with both\n// 'Sync' and 'Abort' effects pending\ndef example1(v: Int \u003c (Sync \u0026 Abort[Exception])) =\n    v.map(_ + 1)\n\n// A value with only the 'Abort' effect can be\n// automatically widened to include 'Sync'\ndef example2(v: Int \u003c Abort[Exception]) =\n    example1(v)\n\n// A pure value can also be automatically widened\ndef example3 = example1(42)\n```\n\nHere, `example1` is designed to accept an `Int \u003c (Options \u0026 Abort[Exception])`. However, thanks to the contravariant encoding of the type-level set of effects, `example2` and `example3` demonstrate that you can also pass in computations with a smaller set of effects—or even a pure value—and they will be automatically widened to fit the expected type.\n\n### Using effects\n\nEffects follow a naming convention for common operations:\n\n- `init*`: Initializes an instance of the container type handled by the effect. For instance, `Fiber.init` returns a new `Fiber`.\n- `get*`: Allows the \"extraction\" of the value of the container type. `Abort.get` can turn an `Either[E, A]` into an `A \u003c Abort[E]`.\n- `run*`: Handles a given effect, transforming the result, pending any remaining effects.\n\nThough named `run`, effect handling doesn't necessarily execute the computation immediately, as the effect handling itself can also be suspended if another effect is pending.\n\n```scala\nimport kyo.*\n\nval a: Int \u003c Abort[Exception] = 42\n\n// Handle the 'Abort' effect\n// 'Result' is similar to 'Either'\nval b: Result[Exception, Int] \u003c Any =\n    Abort.run(a)\n\n// Retrieve pure value as there are no more pending effects\nval c: Result[Exception, Int] =\n    b.eval\n```\n\nThe order in which you handle effects in Kyo can influence both the type and value of the result. Since effects are unordered at the type level, the runtime behavior depends on the sequence in which effects are processed.\n\n```scala\nimport kyo.*\n\ndef abortStringFirst(a: Int \u003c (Abort[String] \u0026 Abort[Exception])): Result[Exception, Result[String, Int]] =\n    val b: Result[String, Int] \u003c Abort[Exception] =\n        Abort.run[String](a)\n    val c: Result[Exception, Result[String, Int]] \u003c Any =\n        Abort.run[Exception](b)\n    c.eval\nend abortStringFirst\n\n// Note how 'Abort' supports type unions. This method's parameter is equivalent to 'abortStringFirst'.\ndef abortExceptionFirst(a: Int \u003c Abort[String | Exception]): Result[String, Result[Exception, Int]] =\n    val b: Result[Exception, Int] \u003c Abort[String] =\n        Abort.run[Exception](a)\n    val c: Result[String, Result[Exception, Int]] \u003c Any =\n        Abort.run[String](b)\n    c.eval\nend abortExceptionFirst\n\n// The sequence in which effects are handled has a significant impact on the outcome.\n// This is especially true for effects that can short-circuit the computation.\n\nval ex = new Exception\n\n// If the computation doesn't short-circuit, only the order of nested types in the result changes.\n// This code uses a pure value as the computation as an example.\nval a: Result[Exception, Result[String, Int]] = abortStringFirst(1)    // Result.Success(Result.Success(1))\nval b: Result[String, Result[Exception, Int]] = abortExceptionFirst(1) // Result.Success(Result.Success(1))\n\n// If there's short-circuiting, the resulting value can be different depending on the handling order.\nabortStringFirst(Abort.fail(\"test\"))    // Result.Success(Result.Fail(\"test\"))\nabortStringFirst(Abort.fail(ex))        // Result.Fail(ex)\n\nabortExceptionFirst(Abort.fail(\"test\")) // Result.Fail(\"test\")\nabortExceptionFirst(Abort.fail(ex))     // Result.Success(Result.Fail(ex))\n```\n\n### Testing effects\n\nKyo currently provides an integration with `zio-test` to enable easier testing of effectful functions.\n\nTo create a test, you can use the `KyoSpecDefault` trait, found under `kyo.test` package in the `kyo-zio-test` library.\n\nYou need to define the following in your `build.sbt`:\n\n```scala mdoc:skip\nlazy val libraryDependencies ++= Seq(\n  // We need this to run the kyo tests with sbt\n  \"dev.zio\" %% \"zio-test-sbt\" % zioVersion % Test,\n  \"io.getkyo\" %% \"kyo-zio-test\" % kyoVersion % Test\n)\n\nlazy val testFrameworksSettings = Seq(\n  // configure the test framework with sbt\n  Test / testFrameworks += new TestFramework(\"zio.test.sbt.ZTestFramework\")\n)\n```\n\nThen you can create a test like this:\n\n```scala\nimport kyo.*\nimport kyo.test.*\n// We use Kyo's Result type, ignoring zio.test.Result\nimport zio.test.{Result as _, *}\n\nobject SimpleTest extends KyoSpecDefault:\n\n  def spec: Spec[Any, Any] =\n    suite(\"test suite\")(\n      test(\"simple test\") {\n        for\n          result \u003c- Abort.run(42)\n        yield assertTrue(result == Result.succeed(42))\n      }\n    )\n```\n\n### Direct Syntax\n\nKyo provides direct syntax for a more intuitive and concise way to express computations, especially when dealing with multiple effects. This syntax leverages three constructs: `direct`, `.now`, and `.later`.\n\nThe `.now` operator sequences an effect immediately, making its result available for use, while `.later` (advanced API) preserves an effect without immediate sequencing for more controlled composition.\n\n```scala\nimport kyo.*\n\n// Use the direct syntax\nval a: String \u003c (Abort[Exception] \u0026 Sync) =\n    direct {\n        val b: String =\n            Sync.defer(\"hello\").now\n        val c: String =\n            Abort.get(Right(\"world\")).now\n        b + \" \" + c\n    }\n\n// Equivalent desugared\nval b: String \u003c (Abort[Exception] \u0026 Sync) =\n    Sync.defer(\"hello\").map { b =\u003e\n        Abort.get(Right(\"world\")).map { c =\u003e\n            b + \" \" + c\n        }\n    }\n```\n\nThe `direct` macro translates the `direct` and `.now`/`.later` constructs by virtualizing control flow. It modifies value definitions, conditional branches, loops, and pattern matching to express computations in terms of `map`. \n\nFor added safety, the direct syntax enforces effectful hygiene. Within a `direct` block, values of the `\u003c` type must be explicitly handled using either `.now` or `.later`. This approach ensures all effectful computations are explicitly processed, reducing the potential for missed effects or operation misalignment.\n\n```scala \nimport kyo.*\n\n// This code fails to compile\nval a: Int \u003c Sync =\n    direct {\n        // Incorrect usage of a '\u003c' value\n        // without '.now' or '.later'\n        Sync.defer(println(42))\n        42\n    }\n```\n\n\u003e Note: In the absence of effectful hygiene, the side effect `Sync.defer(println(42))` would be overlooked and never executed. With the hygiene in place, such code results in a compilation error.\n\nThe `.now` operator is used when you need the effect's result immediately, while `.later` is an advanced operation that preserves the effect without sequencing it:\n\n```scala\nimport kyo.*\n\n// Using .now for immediate sequencing\nval immediate = direct {\n    val x: Int = Sync.defer(1).now      // Get result here\n    val y: Int = Sync.defer(2).now      // Then get this result\n    x + y                       // Use both results\n}\n\n// Using .later for preserved effects\nval preserved = direct {\n    val effect1: Int \u003c Sync = Sync.defer(1).later   // Effect preserved\n    val effect2: Int \u003c Sync = Sync.defer(2).later   // Effect preserved\n    effect1.now + effect2.now             // Sequence effects\n}\n\n// Combining both approaches\nval combined = direct {\n    val effect1: Int \u003c Sync = Sync.defer(1).later   // Effect preserved\n    val effect2: Int = Sync.defer(2).now          // Effect sequenced\n    effect1.now + effect2                 // Combine results\n}\n```\n\nThe direct syntax supports a variety of constructs to handle effectful computations. These include pure expressions, value definitions, control flow statements like `if`-`else`, logical operations (`\u0026\u0026` and `||`), `while`, and pattern matching.\n\n```scala\nimport kyo.*\n\ndirect {\n    // Pure expression\n    val a: Int = 5\n\n    // Effectful value\n    val b: Int = Sync.defer(10).now\n\n    // Control flow\n    val c: String =\n        if Sync.defer(true).now then \"True branch\" else \"False branch\"\n\n    // Logical operations\n    val d: Boolean =\n        Sync.defer(true).now \u0026\u0026 Sync.defer(false).now\n\n    val e: Boolean =\n        Sync.defer(true).now || Sync.defer(true).now\n\n    // Loop (for demonstration; this loop\n    // won't execute its body)\n    while Sync.defer(false).now do \"Looping\"\n\n    // Pattern matching\n    val matchResult: String =\n        Sync.defer(1).now match\n            case 1 =\u003e \"One\"\n            case _ =\u003e \"Other\"\n}\n```\n\nIn addition to control flow, the direct syntax also supports working directly with data structures such as `Option[?]`, `Try[?]`, `Either[?, ?]`, `Seq[?]`, and `Map[?, ?]`. \nThis enables effectful operations to be seamlessly integrated with common collections and containers:\n\n```scala\nimport kyo.*\n\ndef greet(name: String): Unit \u003c Sync =\n  Console.printLine(s\"hello $name!\")\n\nval maybeName: Option[String] = Some(\"Alice\")\n\ndirect {\n  maybeName.foreach(name =\u003e greet(name).now)\n}\n\nval computations: Seq[Int \u003c Abort[String]] = \n  Seq(1, 2, Abort.fail(\"Oops\"))\n\nval sequenced: Seq[Int] \u003c Abort[String] = direct {\n  computations.map(_.now)\n}\n```\n\nThe `direct` method in Kyo mirrors Scala's `for`-comprehensions in providing a constrained yet expressive syntax. In `direct`, features like nested `direct` blocks, `var` declarations, `return` statements, `lazy val`, `lambda` and `def` with `.now`, `try`/`catch` blocks, methods and constructors accepting by-name parameters, `throw` expressions, as well as `class`, `for`-comprehension, `trait`, and `object`s are disallowed. This design allows clear virtualization of control flow, eliminating potential ambiguities or unexpected results.\n\nThe `kyo-direct` module is constructed as an integration with [dotty-cps-async](https://github.com/rssh/dotty-cps-async).\n\n### Defining an App\n\n`KyoApp` offers a structured approach similar to Scala's `App` for defining application entry points. However, it comes with added capabilities, handling a suite of default effects. As a result, the `run` method within `KyoApp` can accommodate various effects, such as Sync, Async, Scope, Clock, Console, Random, Timer, and Aspect.\n\n```scala\nimport kyo.*\n\nobject MyApp extends KyoApp:\n    // Use 'run' blocks to execute Kyo computations.\n    run {\n        for\n            _            \u003c- Console.printLine(s\"Main args: $args\")\n            currentTime  \u003c- Clock.now\n            _            \u003c- Console.printLine(s\"Current time is: $currentTime\")\n            randomNumber \u003c- Random.nextInt(100)\n            _            \u003c- Console.printLine(s\"Generated random number: $randomNumber\")\n        yield\n        // The produced value can be of any type and is\n        // automatically printed to the console using `Render`\n        \"example\"\n    }\nend MyApp\n```\n\nWhile the companion object of `KyoApp` provides a utility method to run isolated effectful computations, it's crucial to approach it with caution. Direct handling the `Sync` effect through this method compromises referential transparency, an essential property for functional programming.\n\n```scala\nimport kyo.*\n\n// An example computation\nval a: Int \u003c Sync =\n    Sync.defer(Math.cos(42).toInt)\n\n// Avoid! Run the application with a timeout\nval b: Result[Throwable, Int] =\n    import AllowUnsafe.embrace.danger\n    KyoApp.Unsafe.runAndBlock(2.minutes)(a)\n```\n\n### Displaying Kyo types\n\nDue to the extensive use of opaque types in Kyo, logging Kyo values can lead to confusion, as the output of `toString` will often leave out type information we are used to seeing in boxed types. For instance, when a pure value is lifted to a pending computation, you will see only that value when you print it.\n\n```scala\nimport kyo.*\n\nval a: Int \u003c Any = 23\nConsole.printLine(s\"Kyo effect: $a\")\n// Ouput: Kyo effect: 23\n```\n\nThis can be jarring to new Kyo users, since we would expect a Kyo computation to be something more than just a pure value. In fact, Kyo's ability to treat pure values as effects is part of what makes it so performant. Nevertheless, the string representations can mislead us about the types of values we log. To make things clearer, Kyo provides a `Render` utility to generate clearer string representation of types:\n\n```scala\nimport kyo.*\n\nval a: Int \u003c Any = 23\n\nval aStr: Text = Render.asText(a)\n\nConsole.printLine(s\"Kyo effect: $aStr\")\n// Output: Kyo effect: Kyo(23)\n```\n\nWe can still see the pure value (23) in the output, but now we can also see that it is a `Kyo`. This will work similarly for other unboxed types like `Maybe` and `Result` (see below). \n\nNote that `Render` does not convert to string but to `Text`--an enriched `String` alternative provided and used internally by Kyo. Kyo methods for displaying strings all accept `Text` values (see `Console` and `Log`, below). Converting values using `Render` directly can be cumbersome, however, so Kyo also provides a string interpolator to construct properly formatted `Text`s automatically. To use this interpolator, prefix your interpolated strings with `t` instead of `s`.\n\n```scala\nimport kyo.*\n\nval a: Int \u003c Any = 23\n\nConsole.printLine(t\"Kyo effect: $a, Kyo maybe: ${Maybe(23)}\")\n// Output: Kyo effect: Kyo(23), Kyo maybe: Present(23)\n```\n\nWe recommend using `t` as the default string interpolator in Kyo applications for the best developer experience.\n\n## Core Effects\n\nKyo's core effects act as the essential building blocks that power your application's various functionalities. Unlike other libraries that might require heavy boilerplate or specialized knowledge, Kyo's core effects are designed to be straightforward and flexible. These core effects not only simplify the management of side-effects, dependencies, and several other aspects but also allow for a modular approach to building maintainable systems.\n\n### Abort: Short Circuiting\n\nThe `Abort` effect is a generic implementation for short-circuiting effects. It's equivalent to ZIO's failure channel.\n\n```scala\nimport kyo.*\n\n// The 'get' method \"extracts\" the value\n// from an 'Either' (right projection)\nval a: Int \u003c Abort[String] =\n    Abort.get(Right(1))\n\n// short-circuiting via 'Left'\nval b: Int \u003c Abort[String] =\n    Abort.get(Left(\"failed!\"))\n\n// short-circuiting via 'Fail'\nval c: Int \u003c Abort[String] =\n    Abort.fail(\"failed!\")\n\n// 'catching' automatically catches exceptions\nval d: Int \u003c Abort[Exception] =\n    Abort.catching(throw new Exception)\n```\n\nTo handle a potentially aborting effect, you can use `Abort.run`. This will produce a `Result`, a high-performance Kyo type equivalent to `Either`:\n\n```scala\nimport kyo.*\n\n// The 'get' method \"extracts\" the value\n// from an 'Either' (right projection)\nval a: Int \u003c Abort[String] =\n    Abort.get(Right(1))\n\n// short-circuiting via 'Left'\nval b: Int \u003c Abort[String] =\n    Abort.get(Left(\"failed!\"))\n\nval aRes: Result[String, Int] \u003c Any = Abort.run(a)\nval bRes: Result[String, Int] \u003c Any = Abort.run(b)\n\n// Note we use a t-string since Result is an unboxed type\nprintln(t\"A: ${aRes.eval}, B: ${bRes.eval}\")\n// Output: A: Success(1), B: Fail(failed!)\n```\n\nNote that `Kyo` has two error channels: an explicitly typed channel represented by `Abort[E]` as well as a `Throwable` \"panic\" channel for unexpected errors. The `Result` generated by `Abort.run` includes both `Failure[E]` and `Panic` error cases. To handle `Failure[E]` without also handling `Panic`, you can use `Abort.runPartial`, which will produce a `Result.Partial[E, A]`, a subtype of `Result` consisting of only `Success[A] | Failure[E]` (note that if the effect panics it will throw the underlying exception). Alternatively, you can use `Abort.fold`, which is overloaded to handle either all three cases or just success and failure.\n\n\u003e Note that the `Abort` effect has a type parameter and its methods can only be accessed if the type parameter is provided.\n\n### Sync: Side Effects\n\nKyo is unlike traditional effect systems since its base type `\u003c` does not assume that the computation can perform side effects. The `Sync` effect is introduced whenever a side effect needs to be performed.\n\n```scala\nimport kyo.*\n\ndef writeBytes = 1 // placeholder\n\n// 'apply' is used to suspend side effects\nval a: Int \u003c Sync =\n    Sync.defer(writeBytes)\n```\n\nUsers shouldn't typically handle the `Sync` effect directly since it triggers the execution of side effects, which breaks referential transparency. Prefer `KyoApp` instead.\n\nIn some specific cases where Kyo isn't used as the main effect system of an application, it might be necessary to handle the Sync effect directly. However, this requires explicit acknowledgment of the unsafe nature of the operation using `AllowUnsafe.embrace.danger`. The `run` method can only be used if `Sync` is the only pending effect.\n\n```scala\nimport kyo.*\n\nval a: Int \u003c Sync =\n    Sync.defer(42)\n\n// ** Avoid 'Sync.Unsafe.run', use 'KyoApp' instead. **\nval b: Int \u003c Abort[Nothing] =\n    import AllowUnsafe.embrace.danger // Required for unsafe operations\n    Sync.Unsafe.run(a)\n// ** Avoid 'Sync.Unsafe.run', use 'KyoApp' instead. **\n```\n\n\u003e IMPORTANT: Avoid handling the `Sync` effect directly since it breaks referential transparency. Use `KyoApp` instead.\n\n### Env: Dependency Injection\n\n`Env` is similar to ZIO's environment feature but offers more granular control. Unlike ZIO, which has built-in layering for dependencies, `Env` allows you to inject individual services directly. Env can be combined with Layers for automated dependency injection.\n\n```scala\nimport kyo.*\n\n// Given an interface\ntrait Database:\n    def count: Int \u003c Sync\n\n// The 'Env' effect can be used to summon an instance.\n// Note how the computation produces a 'Database' but at the\n// same time requires a 'Database' from its environment\nval a: Database \u003c Env[Database] =\n    Env.get[Database]\n\n// Use the 'Database' to obtain the count\nval b: Int \u003c (Env[Database] \u0026 Sync) =\n    a.map(_.count)\n\n// A 'Database' mock implementation\nval db = new Database:\n    def count = 1\n\n// Handle the 'Env' effect with the mock database\nval c: Int \u003c Sync =\n    Env.run(db)(b)\n\n// Additionally, a computation can require multiple values\n// from its environment.\n\n// A second interface to be injected\ntrait Cache:\n    def clear: Unit \u003c Sync\n\n// A computation that requires two values\nval d: Unit \u003c (Env[Database] \u0026 Env[Cache] \u0026 Sync) =\n    Env.get[Database].map { db =\u003e\n        db.count.map {\n            case 0 =\u003e\n                Env.get[Cache].map(_.clear)\n            case _ =\u003e\n                ()\n        }\n    }\n```\n\n### Layer: Dependency Management\n\nThe Layer effect builds upon `Env` to provide a more structured approach to dependency management. It allows you to define, compose, and provide dependencies in a modular and reusable way.\n\n`Layer` is defined with two type parameters: `Layer[Out, S]`\n\n1. `Out`: This represents the output type of the layer, which is the type of the dependency or service that the layer provides. It can be a single type or a combination of types using `\u0026` as a type intersection.\n2. `S`: This represents the set of effects that the layer requires to build its output. It includes any effects needed to construct the `Out` type.\n\nFor example, `Layer[Database, Sync]` represents a layer that provides a `Database` service and has the `Sync` effect to construct it.\n\nNow, let's look at how to create and use layers:\n\n```scala\nimport kyo.*\n\n// Define some services\ntrait Database:\n    def query: String \u003c Sync\n\ntrait Cache:\n    def get: Int \u003c Sync\n\ntrait Logger:\n    def log(msg: String): Unit \u003c Sync\n\n// Create layers for each service\nval dbLayer: Layer[Database, Any] =\n    Layer {\n        new Database:\n            def query = Sync.defer(\"DB result\")\n    }\n\nval cacheLayer: Layer[Cache, Any] =\n    Layer {\n        new Cache:\n            def get = Sync.defer(42)\n    }\n\nval loggerLayer: Layer[Logger, Any] =\n    Layer {\n        new Logger:\n            def log(msg: String) = Sync.defer(println(msg))\n    }\n\n// The `Layer.init` method provides a way to create a layer from multiple sub-layers, automatically \n// resolving dependencies between them. It can be used for more complex compositions as well\nval appLayer: Layer[Database \u0026 Cache \u0026 Logger, Any] =\n    Layer.init[Database \u0026 Cache \u0026 Logger](dbLayer, cacheLayer, loggerLayer)\n\n// Use the composed layer in a computation\nval computation: String \u003c (Env[Database] \u0026 Env[Cache] \u0026 Env[Logger] \u0026 Sync) =\n    for\n        db     \u003c- Env.get[Database]\n        cache  \u003c- Env.get[Cache]\n        logger \u003c- Env.get[Logger]\n        _      \u003c- logger.log(\"Starting query\")\n        result \u003c- db.query\n        _      \u003c- logger.log(s\"Query result: $result\")\n        cached \u003c- cache.get\n        _      \u003c- logger.log(s\"Cached value: $cached\")\n    yield result\n\n// Run the computation with the composed layer\nval result: String \u003c (Sync \u0026 Memo) =\n    Env.runLayer(appLayer)(computation)\n\n// The 'Memo' effect is used by Layer to ensure components are initialized only once\nval result2: String \u003c Sync =\n    Memo.run(result)\n```\n\nThe `Layer` type provides instance methods for manually composing layers:\n\n1. `to`: Combines two layers sequentially, where the output of the first layer is used as input for the second layer.\n2. `and`: Combines two layers in parallel, producing a layer that provides both outputs.\n3. `using`: Combines a layer with another layer that depends on its output, similar to `to` but keeps both outputs.\n\nHere's an example that demonstrates the differences between these methods:\n\n```scala\nimport kyo.*\n\ntrait Database:\n    def query: String \u003c Sync\n\ntrait UserService:\n    def getUser(id: Int): String \u003c Sync\n\ntrait EmailService:\n    def sendEmail(to: String, content: String): Unit \u003c Sync\n\n// Define layers\nval dbLayer: Layer[Database, Sync] = Layer {\n    new Database:\n        def query = Sync.defer(\"DB result\")\n}\n\nval userServiceLayer: Layer[UserService, Env[Database] \u0026 Sync] =\n    Layer.from { (db: Database) =\u003e\n        new UserService:\n            def getUser(id: Int) = db.query.map(result =\u003e s\"User $id: $result\")\n    }\n\nval emailServiceLayer: Layer[EmailService, Sync] = Layer {\n    new EmailService:\n        def sendEmail(to: String, content: String) =\n            Sync.defer(println(s\"Email sent to $to: $content\"))\n}\n\n// Example of `to`: Output of dbLayer is used as input for userServiceLayer\nval dbToUserService: Layer[UserService, Sync] =\n    dbLayer.to(userServiceLayer)\n\n// Example of `and`: Combines dbLayer and emailServiceLayer in parallel\nval dbAndEmail: Layer[Database \u0026 EmailService, Sync] =\n    dbLayer.and(emailServiceLayer)\n\n// Example of `using`: Similar to `to`, but keeps both Database and UserService\nval dbUsingUserService: Layer[Database \u0026 UserService, Sync] =\n    dbLayer.using(userServiceLayer)\n\n// Complex composition\nval fullAppLayer: Layer[Database \u0026 UserService \u0026 EmailService, Sync] =\n    dbLayer.using(userServiceLayer).and(emailServiceLayer)\n\n// Use the full app layer\nval computation: Unit \u003c (Env[Database] \u0026 Env[UserService] \u0026 Env[EmailService] \u0026 Sync) =\n    for\n        db           \u003c- Env.get[Database]\n        userService  \u003c- Env.get[UserService]\n        emailService \u003c- Env.get[EmailService]\n        _            \u003c- db.query\n        user         \u003c- userService.getUser(1)\n        _            \u003c- emailService.sendEmail(\"user@example.com\", s\"User data: $user\")\n    yield ()\n\nval result: Unit \u003c (Sync \u0026 Memo) =\n    Env.runLayer(fullAppLayer)(computation)\n```\n\n### Local: Scoped Values\n\nThe `Local` effect operates on top of `Sync` and enables the definition of scoped values. This mechanism is typically used to store contextual information of a computation. For example, in request processing, locals can be used to store information about the user who initiated the request. This provides a functionality similar to `ThreadLocal`s but with a more flexible scoping to effectful programs.\n\n```scala\nimport kyo.*\n\n// Local need to be initialized with a default value\nval myLocal: Local[Int] =\n    Local.init(0)\n\n// The 'get' method returns the current value of the local (in this case, 0)\nval a: Int \u003c Sync =\n    myLocal.get\n\n// The 'let' method assigns a value to a local within the\n// scope of a computation. This effect produces 43 (42 + 1)\nval b: Int \u003c Sync =\n    myLocal.let(42)(a.map(_ + 1))\n```\n\n\u003e Note: Kyo's effects are designed so locals are properly propagated. For example, they're automatically inherited by forked computations in `Async`.\n\n### Scope: Resource Safety\n\nThe `Scope` effect handles the safe use of external resources like network connections, files, and any other resource that needs to be freed once the computation finalizes. It serves as a mechanism similar to ZIO's `Scope`.\n\n```scala\nimport java.io.Closeable\nimport kyo.*\n\nclass Database extends Closeable:\n    def count: Int \u003c Sync = 42\n    def close()          = {}\n\n// The `acquire` method accepts any object that\n// implements Java's `Closeable` interface\nval db: Database \u003c (Scope \u0026 Async) =\n    Scope.acquire(new Database)\n\n// Use `run` to handle the effect, while also\n// closing the resources utilized by the\n// computation\nval b: Int \u003c Async =\n    Scope.run(db.map(_.count))\n\n// The `ensure` method provides a low-level API to handle the finalization of\n// resources directly. The `acquire` method is implemented in terms of `ensure`.\n\n// Example method to execute a function on a database\ndef withDb[T](f: Database =\u003e T \u003c Async): T \u003c (Scope \u0026 Async) =\n    // Initializes the database ('new Database' is a placeholder)\n    Sync.defer(new Database).map { db =\u003e\n        // Registers `db.close` to be finalized\n        Scope.ensure(db.close).andThen {\n            // Invokes the function\n            f(db)\n        }\n    }\n\n// Execute a function\nval c: Int \u003c (Scope \u0026 Async) =\n    withDb(_.count)\n\n// Close resources\nval d: Int \u003c Async =\n    Scope.run(c)\n```\n\n### Batch: Efficient Data Processing\n\nThe `Batch` effect provides a mechanism for efficient processing of data in batches, allowing for optimized handling of datasets. It includes a type parameter `S` that represents the possible effects that can occur in the data sources.\n\n```scala\nimport kyo.*\n\n// Using 'Batch.sourceSeq' for processing the entire sequence at once, returning a 'Seq'\nval source1 = Batch.sourceSeq[Int, String, Any] { seq =\u003e\n    seq.map(i =\u003e i.toString)\n}\n\n// Using 'Batch.sourceMap' for processing the entire sequence at once, returning a 'Map'\nval source2 = Batch.sourceMap[Int, String, Sync] { seq =\u003e\n    // Source functions can perform arbitrary effects like 'Sync' before returning the results\n    Sync.defer {\n        seq.map(i =\u003e i -\u003e i.toString).toMap\n    }\n}\n\n// Using 'Batch.source' for individual effect suspensions\n// This is a more generic method that allows effects for each of the inputs\nval source3 = Batch.source[Int, String, Sync] { seq =\u003e\n    val map = seq.map { i =\u003e\n        i -\u003e Sync.defer((i * 2).toString)\n    }.toMap\n    (i: Int) =\u003e map(i)\n}\n\n// Example usage\nval result =\n    for\n        a \u003c- Batch.eval(Seq(1, 2, 3))\n        b1 \u003c- source1(a)\n        b2 \u003c- source2(a)\n        b3 \u003c- source3(a)\n    yield (a, b1, b2, b3)\n\n// Handle the effect\nval finalResult: Seq[(Int, String, String, String)] \u003c Sync =\n    Batch.run(result)\n```\n\nWhen creating a source, it's important to note that the returned sequence must have the same number of elements as the input sequence. This restriction ensures consistent behavior and allows for proper batching of operations.\n\n```scala\nimport kyo.*\n\n// This is valid\nval validSource = Batch.sourceSeq[Int, String, Any] { seq =\u003e\n    seq.map(_.toString)\n}\n\n// This would cause a runtime error\nval invalidSource = Batch.sourceSeq[Int, Int, Any] { seq =\u003e\n    seq.filter(_ % 2 == 0)\n}\n```\n\nIt's crucial to understand that the batching is done based on the identity of the provided source function. To ensure proper batching, it's necessary to reuse the function returned by `Batch.source`. Creating a new source for each operation will prevent effective batching. For example:\n\n```scala\nimport kyo.*\n\n// Correct usage: reusing the source\nval source = Batch.sourceSeq[Int, Int, Sync] { seq =\u003e \n    Sync.defer(seq.map(_ * 2))\n}\n\nval goodBatch = for\n    a \u003c- Batch.eval(1 to 1000)\n    b \u003c- source(a)  // This will be batched\n    c \u003c- source(b)  // This will also be batched\nyield c\n\n// Incorrect usage: creating new sources inline\nval badBatch = for\n    a \u003c- Batch.eval(1 to 1000)\n    b \u003c- Batch.sourceSeq[Int, Int, Sync](seq =\u003e Sync.defer(seq.map(_ * 2)))(a)  // This won't be batched\n    c \u003c- Batch.sourceSeq[Int, Int, Sync](seq =\u003e Sync.defer(seq.map(_ * 2)))(b)  // This also won't be batched\nyield c\n```\n\n### Choice: Exploratory Branching\n\nThe `Choice` effect is designed to aid in handling and exploring multiple options, pathways, or outcomes in a computation. This effect is particularly useful in scenario where you're dealing with decision trees, backtracking algorithms, or any situation that involves dynamically exploring multiple options.\n\n```scala\nimport kyo.*\n\n// Evaluate each of the provided `Seq`s.\n// Note how 'get' takes a 'Seq[T]'\n// and returns a 'T \u003c Choice'\nval a: Int \u003c Choice =\n    Choice.eval(1, 2, 3, 4)\n\n// 'dropIf' discards the current element if\n// a condition is not met. Produces a 'Seq(1, 2)'\n// since values greater than 2 are dropped\nval b: Int \u003c Choice =\n    a.map(v =\u003e Choice.dropIf(v \u003e 2).map(_ =\u003e v))\n\n// 'drop' unconditionally discards the\n// current choice. Produces a 'Seq(42)'\n// since only the value 1 is transformed\n// to 42 and all other values are dropped\nval c: Int \u003c Choice =\n    b.map {\n        case 1 =\u003e 42\n        case _ =\u003e Choice.drop\n    }\n\n// Handle the effect to evaluate all elements\n// and return a 'Seq' with the results\nval d: Seq[Int] \u003c Any =\n    Choice.run(c)\n```\n\nThe `Choice` effect becomes exceptionally powerful when combined with other effects. This allows you not just to make decisions or explore options in isolation but also to do so in contexts that may involve factors such as asynchronicity, resource management, or even user interaction.\n\n\n### Loop: Efficient Recursion\n\n`Loop` provides a solution for efficient recursion in Kyo. It offers a set of methods to transform input values through repeated applications of a function until a termination condition is met, allowing for safe and efficient recursive computations without the need for explicit effect suspensions.\n\n```scala\nimport kyo.*\nimport java.io.IOException\n\n// Iteratively increment an 'Int' value\n// until it reaches 5\nval a: Int \u003c Any =\n    Loop(1)(i =\u003e\n        if i \u003c 5 then Loop.continue(i + 1)\n        else Loop.done(i)\n    )\n\n// Transform with multiple input values\nval b: Int \u003c Any =\n    Loop(1, 1)((i, j) =\u003e\n        if i + j \u003c 5 then Loop.continue(i + 1, j + 1)\n        else Loop.done(i + j)\n    )\n\n// Mixing 'Sync' with 'Loop'\nval d: Int \u003c Sync =\n    Loop(1)(i =\u003e\n        if i \u003c 5 then\n            Sync.defer(println(s\"Iteration: $i\")).map(_ =\u003e Loop.continue(i + 1))\n        else\n            Loop.done(i)\n    )\n\n// Mixing 'Console' with 'Loop'\nval e: Int \u003c (Sync \u0026 Abort[IOException]) =\n    Loop(1)(i =\u003e\n        if i \u003c 5 then\n            Console.printLine(s\"Iteration: $i\").map(_ =\u003e Loop.continue(i + 1))\n        else\n            Loop.done(i)\n    )\n```\n\nThe `transform` method takes an initial input value and a function that accepts this value. The function should return either `Loop.continue` with the next input value or `Loop.done` with the final result. The computation continues until `Loop.done` is returned. Similarly, `transform2` and `transform3` allow transformations with multiple input values. \n\nHere's an example showing three versions of the same computation:\n\n```scala\nimport kyo.*\n\n// Version 1: Regular while loop\ndef whileLoop: Int =\n    var i   = 0\n    var sum = 0\n    while i \u003c 10 do\n        sum += i\n        i += 1\n    sum\nend whileLoop\n\n// Version 2: Recursive method loop\ndef recursiveLoop(i: Int = 0, sum: Int = 0): Int =\n    if i \u003c 10 then\n        recursiveLoop(i + 1, sum + i)\n    else\n        sum\n\n// Version 3: Using Loop\ndef loopsVersion: Int \u003c Any =\n    Loop(0, 0)((i, sum) =\u003e\n        if i \u003c 10 then\n            Loop.continue(i + 1, sum + i)\n        else\n            Loop.done(sum)\n    )\n```\n\nIn addition to the transform methods, Loop also provides indexed variants that pass the current iteration index to the transformation function. This can be useful when the logic of the loop depends on the iteration count, such as performing an action every nth iteration or terminating the loop after a certain number of iterations. The indexed methods are available with one, two, or three input values.\n\n```scala\nimport kyo.*\nimport java.io.IOException\n\n// Print a message every 3 iterations\nval a: Int \u003c (Sync \u0026 Abort[IOException]) =\n    Loop.indexed(1)((idx, i) =\u003e\n        if idx \u003c 10 then\n            if idx % 3 == 0 then\n                Console.printLine(s\"Iteration $idx\").map(_ =\u003e Loop.continue(i + 1))\n            else\n                Loop.continue(i + 1)\n        else\n            Loop.done(i)\n    )\n\n// Terminate the loop after 5 iterations\nval b: Int \u003c Any =\n    Loop.indexed(1, 1)((idx, i, j) =\u003e\n        if idx \u003c 5 then Loop.continue(i + 1, j + 1)\n        else Loop.done(i + j)\n    )\n\n// Use the index to calculate the next value\nval c: Int \u003c Any =\n    Loop.indexed(1, 1, 1)((idx, i, j, k) =\u003e\n        if idx \u003c 5 then Loop.continue(i + idx, j + idx, k + idx)\n        else Loop.done(i + j + k)\n    )\n```\n\n### Memo: Function Memoization\n\nThe `Memo` effect in Kyo provides a mechanism for memoizing (caching) the results of function calls. It's implemented as a specialized `Var` effect that manages a cache of function results.\n\n```scala\nimport kyo.*\n\nval fibonacci: Int =\u003e Int \u003c Memo = \n    Memo { n =\u003e\n        if (n \u003c= 1) n\n        else\n            for\n                a \u003c- fibonacci(n - 1)\n                b \u003c- fibonacci(n - 2)\n            yield a + b\n    }\n\nval result: (Int, Int) \u003c Memo = \n    Memo.run {\n        for\n            fib10 \u003c- fibonacci(10)\n            fib11 \u003c- fibonacci(11)\n        yield (fib10, fib11)\n    }\n\nval result2: (Int, Int) \u003c Any =\n    Memo.run(result)\n```\n\nKey points about `Memo`:\n\n- `Memo` memoizes function results based on both the function's input and a unique internal `MemoIdentity` for each memoized function.\n- Memoization is scoped to the `Memo.run` block. A new cache is created at the start of the block and discarded at the end.\n- `Memo` works seamlessly with other Kyo effects, allowing memoization of effectful computations.\n- The memoization cache uses structural equality for keys, making it effective with immutable data structures.\n- Each memoized function has its own cache space, even if created with identical code at different call sites.\n\nFor optimizing frequently called functions or computations in performance-critical sections of your code, the Cache effect would be more appropriate. `Memo` is designed for automatic memoization within a specific computation scope, while `Cache` provides more fine-grained control over caching behavior and better performance.\n\n### Chunk: Efficient Sequences\n\n`Chunk` is an efficient mechanism for processing sequences of data in a purely functional manner. It offers a wide range of operations optimized for different scenarios, ensuring high performance without compromising functional programming principles.\n\n`Chunk` is designed as a lightweight wrapper around contiguous collections (`Array`, `IndexedSeq`), allowing for efficient random access and transformation operations. Its internal representation is carefully crafted to minimize memory allocation and ensure stack safety. Many of its operations have an algorithmic complexity of `O(1)`, making them highly performant for a variety of use cases. It extends Scala's `Seq` trait, enabling direct use within other libraries or existing codebases.\n\n```scala\nimport kyo.*\n\n// Construct chunks\nval a: Chunk[Int] = Chunk(1, 2, 3)\nval b: Chunk[Int] = Chunk.from(Seq(4, 5, 6))\n\n// Perform O(1) operations\nval c = a.append(4)\nval d = b.take(2)\nval e = c.dropLeft(1)\n\n// Perform O(n) operations\nval f = d.map(_.toString)\nval g = e.filter(_ % 2 == 0)\n```\n\n`Chunk` provides two main subtypes: `Chunk` for regular chunks and `Chunk.Indexed` for indexed chunks. The table below summarizes the time complexity of various operations for each type:\n\n| Description              | Operations                                           | Regular Chunk | Indexed Chunk |\n| ------------------------ | ---------------------------------------------------- | ------------- | ------------- |\n| Creation                 | `Chunk`, `Chunk.from`                                | O(n)          | O(n)          |\n| Size and emptiness       | `size`, `isEmpty`                                    | O(1)          | O(1)          |\n| Take and drop            | `take`, `dropLeft`, `dropRight`, `slice`             | O(1)          | O(1)          |\n| Append and last          | `append`, `last`                                     | O(1)          | O(1)          |\n| Element access           | `apply`, `head`, `tail`                              | N/A           | O(1)          |\n| Concatenation            | `concat`                                             | O(n)          | O(n)          |\n| Effectful map and filter | `map`, `filter`, `collect`, `takeWhile`, `dropWhile` | O(n)          | O(n)          |\n| Effectful side effects   | `foreach`, `collectUnit`                             | O(n)          | O(n)          |\n| Effectful fold           | `foldLeft`                                           | O(n)          | O(n)          |\n| Copying to arrays        | `toArray`, `copyTo`                                  | O(n)          | O(n)          |\n| Other operations         | `flatten`, `changes`, `toSeq`, `toIndexed`           | O(n)          | O(n)          |\n\nWhen deciding between `Chunk` and `Chunk.Indexed`, consider the primary operations you'll be performing on the data. If you mainly need to `append` elements, `take` slices, or `drop` elements from the beginning or end of the sequence, `Chunk` is a good choice. Its `O(1)` complexity for these operations makes it efficient for such tasks.\n\n```scala\nimport kyo.*\n\nval a: Chunk[Int] = Chunk(1, 2, 3, 4, 5)\n\n// Efficient O(1) operations with Chunk\nval b: Chunk[Int] = a.append(6)\nval c: Chunk[Int] = a.take(3)\nval d: Chunk[Int] = a.dropLeft(2)\n```\n\nOn the other hand, if you frequently need to access elements by index, `Chunk.Indexed` is the better option. It provides `O(1)` element access and supports `head` and `tail` operations, which are not available in `Chunk`.\n\n```scala\nimport kyo.*\n\nval a: Chunk.Indexed[Int] =\n    Chunk(1, 2, 3, 4, 5).toIndexed\n\n// Efficient O(1) operations with Chunk.Indexed\nval b: Int                 = a(2)\nval c: Int                 = a.head\nval d: Chunk.Indexed[Int] = a.tail\n```\n\nKeep in mind that converting between `Chunk` and `Chunk.Indexed` is an `O(n)` operation, so it's best to choose the appropriate type upfront based on your usage patterns. However, calling `toIndexed` on a chunk that is already internally indexed is a no-op and does not incur any additional overhead.\n\nHere's an overview of the main APIs available in Chunk:\n\n```scala\nimport kyo.*\n\n// Creation\nval a: Chunk[Int] = Chunk(1, 2, 3)\nval b: Chunk[Int] = Chunk.from(Seq(4, 5, 6))\n\n// Size and emptiness\nval c: Int     = a.size\nval d: Boolean = a.isEmpty\n\n// Take and drop\nval e: Chunk[Int] = a.take(2)\nval f: Chunk[Int] = a.dropLeft(1)\n\n// Append and last\nval g: Chunk[Int] = a.append(4)\nval h: Int        = a.last\n\n// Concatenation\nval i: Chunk[Int] = a.concat(b)\n\n// Copying to arrays\nval n: Array[Int] = a.toArray\n\n// Flatten a nested chunk\nval o: Chunk[Int] =\n    Chunk(a, b).flattenChunk\n\n// Obtain sequentially distinct elements.\n// Outputs: Chunk(1, 2, 3, 1)\nval p: Chunk[Int] =\n    Chunk(1, 1, 2, 3, 3, 1, 1).changes\n```\n\n### Stream: Composable Data Processing\n\nThe Stream effect provides a powerful mechanism for processing sequences of data in a memory-conscious and composable manner. It offers a rich set of operations for transforming, filtering, and combining streams of data, all while maintaining laziness and ensuring stack safety.\n\n```scala\nimport kyo.*\nimport java.io.IOException\n\n// Create a stream from a sequence\nval a: Stream[Int, Any] =\n    Stream.init(Seq(1, 2, 3, 4, 5))\n\n// Map over stream elements\nval b: Stream[String, Any] =\n    a.map(_.toString)\n\n// Filter stream elements\nval c: Stream[Int, Any] =\n    a.filter(_ % 2 == 0)\n\n// Take a limited number of elements\nval d: Stream[Int, Any] =\n    a.take(3)\n\n// Drop elements from the beginning\nval e: Stream[Int, Any] =\n    a.drop(2)\n\n// Concatenate streams\nval f: Stream[Int, Any] =\n    a.concat(Stream.init(Seq(6, 7, 8)))\n\n// FlatMap over stream elements\nval g: Stream[Int, Any] =\n    a.flatMap(x =\u003e Stream.init(Seq(x, x * 2)))\n\n// Collect stream results into a Chunk\nval h: Chunk[Int] \u003c Any =\n    a.run\n\n// Process stream elements without collecting results\nval i: Unit \u003c Any =\n    a.discard\n\n// Fold over stream elements\nval j: Int \u003c Any =\n    a.fold(0)(_ + _)\n\n// Process each element with side effects\nval k: Unit \u003c (Sync \u0026 Abort[IOException]) =\n    a.foreach(Console.printLine(_))\n```\n\nStreams can be combined with other effects, allowing for powerful and flexible data processing pipelines:\n\n```scala\nimport kyo.*\n\ncase class Config(someConfig: String)\n\n// Stream with Sync effect\nval a: Stream[String, Sync] =\n    Stream.init(Seq(\"file1.txt\", \"file2.txt\"))\n        .map(fileName =\u003e Sync.defer(scala.io.Source.fromFile(fileName).mkString))\n\n// Stream with Abort effect\nval b: Stream[Int, Abort[NumberFormatException]] =\n    Stream.init(Seq(\"1\", \"2\", \"abc\", \"3\"))\n        .map(s =\u003e Abort.catching[NumberFormatException](s.toInt))\n\ndef fetchUserData(config: Config, username: String): Seq[String] \u003c Async =\n    Seq(s\"user data for $username\") // mock implementation\n\n// Combining multiple effects\nval c: Stream[String, Env[Config] \u0026 Async] =\n    Stream.init(Seq(\"user1\", \"user2\", \"user3\"))\n        .flatMap { username =\u003e\n            Stream.init {\n                for\n                    config \u003c- Env.get[Config]\n                    result \u003c- fetchUserData(config, username)\n                yield result\n            }\n        }\n\n// Run the stream and handle effects\nval result: Chunk[String] \u003c (Env[Config] \u0026 Async) =\n    c.run\n```\n\nTo handle one or more effects used by a stream, you can pass effect transformations to the `handle` method. These will be applied to the underlying streaming effect.\n\n```scala\nimport kyo.*\n\ncase class Config(someConfig: String)\n\nval original: Stream[Int, Scope \u0026 Env[Config] \u0026 Abort[String] \u0026 Async] = Stream.init(Seq(1))\n\nval handled: Stream[Int, Async] = original.handle(\n    Scope.run(_),\n    Env.run(Config(\"some config\"))(_),\n    Abort.run[String](_)\n)\n```\n\nTo fuse one or more effects used to create and run a stream, you can use `unwrap` method.\n\n```scala\nimport kyo.*\n\ncase class Config(size:Int)\n\nval original: Stream[Int, Any] \u003c Env[Config] = Env.get[Config].map(config =\u003e Stream.range(-9, 999).take(config.size))\n\nval unwrapped: Stream[Int, Env[Config]] = Stream.unwrap(original) // or original.unwrapStream if you are using kyo-combinators\n\nval handled: Stream[Int, Any] = unwrapped.handle(Env.run(Config(3)))\n\nassert(handled.run.eval == Chunk(-9, -8, -7))\n```\n\nThe `Stream` effect is useful for processing large amounts of data in a memory-efficient manner, as it allows for lazy evaluation and only keeps a small portion of the data in memory at any given time. It's also composable, allowing you to build complex data processing pipelines by chaining stream operations.\n\nNote that a number of `Stream` methods (e.g., `map`, `filter`, `mapChunk`) have variants that only accept pure functions. These variants have suffix `-Pure`. For instance, `mapPure` transforms streamed elements using a function in the form `V =\u003e V1`, whereas `map` transforms elements with a function `V =\u003e V1 \u003c S1` allowing you to use arbitrary effects in the transformation. While any of the non-pure methods will also accept pure functions, since any value can be lifted to a pending type, the `-Pure` variants are optimized for pure functions.\n\n#### Sink: stream evaluation\n\nWhile typically it is sufficient to use the built-in methods on `Stream` to run streams and evaluate them to some value or outcome, it can also be useful to abstract the evaluation into a separate type that can be composed and manipulated separately from any actual stream. For this purpose, Kyo includes a `Sink[V, A, S]` type, inspired by ZIO's `ZSink`, which represents the processing of a stream of element type `V` into an output value of type `A` using effect types `S`.\n\nTo run a stream into a sink, you can use `Stream#into` or `Sink#consume`\n\nAll of the evaluation methods available on `Stream` are available as constructors for `Sink`s, e.g:\n\n```scala\nimport kyo.*\n\nval stream = Stream.init(1 to 10)\n\nval collectValuesSink: Sink[Int, Chunk[Int], Any] = Sink.collect[Int]\nval collectedValues: Chunk[Int] \u003c Any = stream.into(collectValuesSink)\n\nval printValuesSink: Sink[Int, Unit, Sync] = Sink.foreach((v: Int) =\u003e Console.printLine(s\"Value: $v\"))\nval printedValues: Unit \u003c Sync = stream.into(printValuesSink)\n\nval sumValuesSink: Sink[Int, Int, Any] = Sink.fold(0)((a: Int, v: Int) =\u003e a + v)\nval summedValues: Int \u003c Any = stream.into(sumValuesSink)\n```\n\nSinks can then be combined and transformed to produce new sinks:\n\n```scala\nimport kyo.*\n\n// built in sink to count elements in stream\nval countSink: Sink[Int, Int, Any] = Sink.count[Int]\n// add all integers in stream together\nval sumSink: Sink[Int, Int, Any] = Sink.fold(0)((a: Int, v: Int) =\u003e a + v)\n// `zip` combines sinks together, applying them to same stream elements in tandem, and\n// producing a tuple of the output values of each sink.\n// `map` transforms the output value\nval averageSink: Sink[Int, Double, Any] = sumSink.zip(countSink).map { \n    case (sum, count) =\u003e sum / count\n}\n// contramap transforms the sink to consume a different stream type\nval avgStringLengthSink = averageSink.contramap((str: String) =\u003e str.length)\n\nval strings = Stream.init(Seq(\"one\", \"two\", \"three\"))\nval avgStringLength: Double \u003c Any = strings.into(avgStringLengthSink)\n```\n\n#### Pipe: stream transformation\n\nJust as `Sink` can be used to separate the evaluation of streams from the stream itself, `Pipe` provides the ability to construct and manipulate stream transformations independently of any particular stream. A `Pipe[A, B, S]` represents a transformation of `Stream[A, ?]` to `Stream[B, ?]` using effect type `S`.\n\nTo use a pipe to transform a stream, you can use `Stream#into` or `Pipe.transform`.\n\nAll of the transformation combinators on `Stream` are available as `Pipe` constructors, e.g.:\n\n```scala\nimport kyo.*\n\nval stream = Stream.init(1 to 10)\n\nval mapValuesPipe: Pipe[Int, String, Any] = Pipe.map(_.toString)\nval mappedStream: Stream[String, Any] = stream.into(mapValuesPipe)\n\nval printValuesPipe: Pipe[Int, Int, Sync] = Pipe.tap((v: Int) =\u003e Console.printLine(s\"Value: $v\"))\nval printedStream: Stream[Int, Sync] = stream.into(printValuesPipe)\n\nval takeWhilePipe: Pipe[Int, Int, Any] = Pipe.takeWhile[Int](_ \u003c 5)\nval shorterStream: Stream[Int, Any] = stream.into(takeWhilePipe)\n```\n\nPipes can be combined with other pipes to produce new pipes, or with sinks to produce new sinks:\n\n```scala\nimport kyo.*\nimport scala.util.Try\n\nval pipe1 = Pipe.map[String](v =\u003e Try(v.toInt))\nval pipe2 = Pipe.collect[Try[Int]](v =\u003e Maybe.fromOption(v.toOption))\nval sink = Sink.fold[Int, Int](0)(_ + _)\n\nval pipe3 = pipe1.join(pipe2)\nval sink2 = pipe3.join(sink)\n\nval stream = Stream.init(Seq(\"one\", \"tow\", \"three\", \"fuor\", \"five\", \"xis\"))\nval result = stream.into(sink2)\n\n// OR you can just run the stream `into` the pipes and sink\n\nval result2 = stream.into(pipe1).into(pipe2).into(sink)\n```\n\n### Var: Stateful Computations\n\nThe `Var` effect allows for stateful computations, similar to the `State` monad. It enables the management of state within a computation in a purely functional manner.\n\n```scala\nimport kyo.*\n\n// Get the current value\nval a: Int \u003c Var[Int] =\n    Var.get[Int]\n\n// Set a new value and return the previous one\nval b: Int \u003c Var[Int] =\n    Var.set(10)\n\n// Update the state and return the new value\nval c: Int \u003c Var[Int] =\n    Var.update[Int](v =\u003e v + 1)\n\n// Use in a computation\nval d: String \u003c Var[Int] =\n    Var.use[Int](v =\u003e v.toString)\n\n// Handle the effect and discard state\nval e: String \u003c Any =\n    Var.run(10)(d)\n```\n\n`Var` is particularly useful when you need to maintain and manipulate state across multiple steps of a computation.\n\n```scala\nimport kyo.*\n\n// A computation that uses `Var` to maintain a counter\ndef counter[S](n: Int): Int \u003c (Var[Int] \u0026 S) =\n    if n \u003c= 0 then\n        Var.get[Int]\n    else\n        for\n            _      \u003c- Var.update[Int](_ + 1)\n            result \u003c- counter(n - 1)\n        yield result\n\n// Initialize the counter with an initial state\nval a: Int \u003c Any =\n    Var.run(0)(counter(10))\n```\n\nBy combining Var with other effects like Async, you can create stateful computations that can be safely executed concurrently.\n\n### Emit: Accumulating Values\n\nThe `Emit` effect is designed to accumulate values throughout a computation, similar to the `Writer` monad. It collects a `Chunk` of values alongside the main result of a computation.\n\n```scala\nimport kyo.*\n\n// Add a value\nval a: Unit \u003c Emit[Int] =\n    Emit.value(42)\n\n// Add multiple values\nval b: String \u003c Emit[Int] =\n    for\n        _ \u003c- Emit.value(1)\n        _ \u003c- Emit.value(2)\n        _ \u003c- Emit.value(3)\n    yield \"r\"\n\n// Handle the effect to obtain the\n// accumulated log and the result.\n// Evaluates to `(Chunk(1, 2, 3), \"r\")`\nval c: (Chunk[Int], String) \u003c Any =\n    Emit.run(b)\n\n```\n\nWhen running `Emit`, the accumulated values are returned in a `Chunk`. The collected values and the result are returned as a tuple by `Emit.run`, with the `Chunk` as the first element. A computation can also use multiple `Emit` of different types.\n\n```scala\nimport kyo.*\n\nval a: String \u003c (Emit[Int] \u0026 Emit[String]) =\n    for\n        _ \u003c- Emit.value(1)\n        _ \u003c- Emit.value(\"log\")\n        _ \u003c- Emit.value(2)\n    yield \"result\"\n\n// Note how `run` requires an explicit type\n// parameter when a computation has multiple\n// pending `Sum`s.\nval b: (Chunk[Int], (Chunk[String], String)) \u003c Any =\n    Emit.run[Int](Emit.run[String](a))\n```\n\nThe `Emit` effect is useful for collecting diagnostic information, accumulating intermediate results, or building up data structures during a computation.\n\n### Aspect: Aspect-Oriented Programming\n\nThe `Aspect` effect provides a way to modify or intercept behavior across multiple points in a program without directly changing the affected code. It works by allowing users to provide implementations for abstract operations at runtime, similar to dependency injection but with more powerful composition capabilities.\n\nAspects are created using `Aspect.init` and are typically stored as vals at module level. Once initialized, an aspect can be used to wrap computations that need to be modified, and its behavior can be customized using the `let` method to provide specific implementations within a given scope. This pattern allows for clean separation between the definition of interceptable operations and their actual implementations.\n\nAn aspect is parameterized by two type constructors, `Input[_]` and `Output[_]`, along with an effect type `S`. These type constructors define the shape of values that can be processed and produced by the aspect. The underscore in `Input[_]` and `Output[_]` indicates that these are higher-kinded types - they each take a type parameter. This allows aspects to work with generic data structures while preserving type information throughout the transformation chain.\n\nThe simplest way to work with aspects is to use `Const[A]`, which represents a plain value of type `A`. This is useful when you want to transform values directly without additional context or metadata. As you'll see in the more advanced example later, you can also create custom type constructors when you need to carry additional information through the transformation pipeline.\n\nHere's a basic example using `Const`:\n\n```scala\nimport kyo.*\n\ncase class Invalid(reason: String) extends Exception\n\n// Simple aspect that transforms integers\nval numberAspect = Aspect.init[Const[Int], Const[Int], Abort[Throwable] \u0026 Sync]\n\n// Basic processing function\ndef process(n: Int): Int \u003c (Abort[Throwable] \u0026 Sync) =\n    numberAspect(n)(x =\u003e x * 2)\n\n// Add validation via a Cut\nval validationCut =\n    Aspect.Cut[Const[Int], Const[Int], Abort[Throwable] \u0026 Sync](\n        [C] =\u003e\n            (input, cont) =\u003e\n                if input \u003e 0 then cont(input)\n                else Abort.fail(Invalid(\"negative number\"))\n    )\n\n// Add logging via another Cut\nval loggingCut =\n    Aspect.Cut[Const[Int], Const[Int], Abort[Throwable] \u0026 Sync](\n        [C] =\u003e\n            (input, cont) =\u003e\n                for\n                    _      \u003c- Console.printLine(s\"Processing: $input\")\n                    result \u003c- cont(input)\n                    _      \u003c- Console.printLine(s\"Result: $result\")\n                yield result\n    )\n\n// Compose both cuts into one\nval composedCut =\n    Aspect.Cut.andThen(validationCut, loggingCut)\n\n// Success case\nval successExample: Unit \u003c (Abort[Throwable] \u0026 Sync) =\n    for\n        result \u003c-\n            numberAspect.let(composedCut) {\n                process(5) // Will succeed: 5 * 2 -\u003e 10\n            }\n        _ \u003c- Console.printLine(s\"Success result: $result\")\n    yield ()\n\n// Failure case\nval failureExample: Unit \u003c (Abort[Throwable] \u0026 Sync) =\n    for\n        result \u003c-\n            numberAspect.let(composedCut) {\n                process(-3) // Will fail with Invalid(\"negative number\")\n            }\n        _ \u003c- Console.printLine(\"This won't be reached due to Abort\")\n    yield ()\n```\n\nAspects support multi-shot continuations, meaning that cut implementations can invoke the continuation function multiple times or not at all. This enables control flow modifications like retry logic, fallback behavior, or conditional execution. Internally, aspects function as a form of reified ArrowEffect that can be stored, passed around, and modified at runtime. They maintain state through a `Local` map of active implementations, allowing them to be dynamically activated and deactivated through operations like `let` and `sandbox`.\n\nThe following example demonstrates these capabilities with generic type constructors:\n\n```scala\nimport kyo.*\n\n// Define wrapper types that preserve the generic parameter\ncase class Request[+A](value: A, metadata: Map[String, String])\ncase class Response[+A](value: A, status: Int)\n\n// Initialize aspect that can transform any Request to Response\nval serviceAspect = Aspect.init[Request, Response, Sync \u0026 Abort[Throwable]]\n\n// Example service using the aspect\ndef processRequest[A](request: Request[A]): Response[A] \u003c (Sync \u0026 Abort[Throwable]) =\n    serviceAspect(request) { req =\u003e\n        Response(req.value, status = 200)\n    }\n\n// Add authentication via a Cut\nval authCut =\n    Aspect.Cut[Request, Response, Sync \u0026 Abort[Throwable]](\n        [C] =\u003e\n            (input, cont) =\u003e\n                input.metadata.get(\"auth-token\") match\n                    case Some(\"valid-token\") =\u003e cont(input)\n                    case _                   =\u003e Sync.defer(Response(input.value, status = 401))\n    )\n\n// Add logging via another Cut\nval loggingCut =\n    Aspect.Cut[Request, Response, Sync \u0026 Abort[Throwable]](\n        [C] =\u003e\n            (input, cont) =\u003e\n                for\n                    _      \u003c- Console.printLine(s\"Processing request: ${input}\")\n                    result \u003c- cont(input)\n                    _      \u003c- Console.printLine(s\"Response: ${result}\")\n                yield result\n    )\n\n// Compose both cuts into one\nval composedCut =\n    Aspect.Cut.andThen(authCut, loggingCut)\n\n// Example requests\nval req1 = Request(\"hello\", Map(\"auth-token\" -\u003e \"valid-token\"))\nval req2 = Request(42, Map(\"auth-token\" -\u003e \"invalid\"))\n\n// Use the service with both aspects\nval example: Unit \u003c (Sync \u0026 Abort[Throwable]) =\n    for\n        r1 \u003c-\n            serviceAspect.let(composedCut) {\n                processRequest(req1)\n            }\n        r2 \u003c-\n            serviceAspect.let(composedCut) {\n                processRequest(req2)\n            }\n        _ \u003c- Console.printLine(s\"Results: $r1, $r2\")\n    yield ()\n```\n\n### Check: Runtime Assertions\n\nThe `Check` effect provides a mechanism for runtime assertions and validations. It allows you to add checks throughout your code that can be handled in different ways, such collecting failures or discarding them.\n\n```scala\nimport kyo.*\n\n// Create a simple check\nval a: Unit \u003c Check =\n    Check.require(1 + 1 == 2, \"Basic math works\")\n\n// Checks can be composed with other effects\nval b: Int \u003c (Check \u0026 Sync) =\n    for\n        value \u003c- Sync.defer(42)\n        _     \u003c- Check.require(value \u003e 0, \"Value is positive\")\n    yield value\n\n// Handle checks by converting the first failed check to Abort\nval c: Int \u003c (Abort[CheckFailed] \u0026 Sync) =\n    Check.runAbort(b)\n\n// Discard check failures and continue execution\nval e: Int \u003c Sync =\n    Check.runDiscard(b)\n```\n\nThe `CheckFailed` exception class, which is used to represent failed checks, includes both the failure message and the source code location (via `Frame`) where the check failed, making it easier to locate and debug issues.\n\n### Console: Console Interaction\n\n```scala\nimport kyo.*\nimport java.io.IOException\n\n// Read a line from the console\nval a: String \u003c (Sync \u0026 Abort[IOException]) =\n    Console.readLine\n\n// Print to stdout\nval b: Unit \u003c (Sync \u0026 Abort[IOException]) =\n    Console.print(\"ok\")\n\n// Print to stdout with a new line\nval c: Unit \u003c (Sync \u0026 Abort[IOException]) =\n    Console.printLine(\"ok\")\n\n// Print to stderr\nval d: Unit \u003c (Sync \u0026 Abort[IOException]) =\n    Console.printErr(\"fail\")\n\n// Print to stderr with a new line\nval e: Unit \u003c (Sync \u0026 Abort[IOException]) =\n    Console.printLineErr(\"fail\")\n\n// Explicitly specifying the 'Console' implementation\nval f: Unit \u003c (Sync \u0026 Abort[IOException]) =\n    Console.let(Console.live)(e)\n```\n\nNote that `Console.printX` methods accept `Text` values. `Text` is a super-type of `String`, however, so you can just pass regular strings. You can also pass `Text` instances generated from the `t` string interpolator ([see above](#displaying-kyo-types)).\n\n### Clock: Time Management and Scheduled Tasks\n\nThe `Clock` effect provides utilities for time-related operations, including getting the current time, creating stopwatches, and managing deadlines.\n\n```scala\nimport kyo.*\n\n// Obtain the current time\nval a: Instant \u003c Sync =\n    Clock.now\n\n// Create a stopwatch\nval b: Clock.Stopwatch \u003c Sync =\n    Clock.stopwatch\n\n// Measure elapsed time with a stopwatch\nval c: Duration \u003c Sync =\n    for\n        sw      \u003c- Clock.stopwatch\n        elapsed \u003c- sw.elapsed\n    yield elapsed\n\n// Create a deadline\nval d: Clock.Deadline \u003c Sync =\n    Clock.deadline(5.seconds)\n\n// Check time left until deadline\nval e: Duration \u003c Sync =\n    for\n        deadline \u003c- Clock.deadline(5.seconds)\n        timeLeft \u003c- deadline.timeLeft\n    yield timeLeft\n\n// Check if a deadline is overdue\nval f: Boolean \u003c Sync =\n    for\n        deadline \u003c- Clock.deadline(5.seconds)\n        isOverdue \u003c- deadline.isOverdue\n    yield isOverdue\n\n// Run with an explicit `Clock` implementation\nval g: Instant \u003c Sync =\n    Clock.let(Clock.live)(Clock.now)\n```\n\n`Clock` both safe (effectful) and unsafe (non-effectful) versions of its operations. The safe versions are suspended in `Sync` and should be used in most cases. The unsafe versions are available through the `unsafe` property and should be used with caution, typically only in performance-critical sections or when integrating with non-effectful code.\n\n`Clock` also offers methods to schedule background tasks:\n\n```scala\nimport kyo.*\n\n// An example computation to\n// be scheduled\nval a: Unit \u003c Sync =\n    Sync.defer(())\n\n// Recurring task with a delay between\n// executions\nval b: Fiber[Unit, Any] \u003c Sync =\n    Clock.repeatWithDelay(\n        startAfter = 1.minute,\n        delay = 1.minute\n    )(a)\n\n// Without an initial delay\nval c: Fiber[Unit, Any] \u003c Sync =\n    Clock.repeatWithDelay(1.minute)(a)\n\n// Schedule at a specific interval, regardless\n// of the duration of each execution\nval d: Fiber[Unit, Any] \u003c Sync =\n    Clock.repeatAtInterval(\n        startAfter = 1.minute,\n        interval = 1.minute\n    )(a)\n\n// Without an initial delay\nval e: Fiber[Unit, Any] \u003c Sync =\n    Clock.repeatAtInterval(1.minute)(a)\n```\n\nUse the returned `Fiber` to control scheduled tasks.\n\n```scala\nimport kyo.*\n\n// Example task\nval a: Fiber[Unit, Any] \u003c Sync =\n    Clock.repeatAtInterval(1.second)(())\n\n// Try to cancel a task\ndef b(task: Fiber[Unit, Any]): Boolean \u003c Sync =\n    task.interrupt\n\n// Check if a task is done\ndef c(task: Fiber[Unit, Any]): Boolean \u003c Sync =\n    task.done\n```\n\n\n### System: Environment Variables and System Properties\n\nThe `System` effect provides a safe and convenient way to access environment variables and system properties. It offers methods to retrieve values with proper type conversion and fallback options.\n\n```scala\nimport kyo.*\n\n// Get an environment variable as a String\nval a: Maybe[String] \u003c Sync =\n    System.env[String](\"PATH\")\n\n// Get an environment variable with a default value\nval b: String \u003c Sync =\n    System.env[String](\"CUSTOM_VAR\", \"default\")\n\n// Get a system property as an Int.\nval c: Maybe[Int] \u003c (Abort[NumberFormatException] \u0026 Sync) =\n    System.property[Int](\"java.version\")\n\n// Get a system property with a default value\nval d: Int \u003c (Abort[NumberFormatException] \u0026 Sync) =\n    System.property[Int](\"custom.property\", 42)\n\n// Get the line separator for the current platform\nval e: String \u003c Sync =\n    System.lineSeparator\n\n// Get the current user's name\nval f: String \u003c Sync =\n    System.userName\n\n// Use a custom System implementation\nval g: String \u003c Sync =\n    System.let(System.live)(System.userName)\n```\n\nThe `System` effect provides built-in parsers for common types like `String`, `Int`, `Boolean`, `Double`, `Long`, `Char`, `Duration`, and `UUID`. Custom parsers can be implemented by providing an implicit `System.Parser[E, A]` instance.\n\n### Random: Random Values\n\n```scala\nimport kyo.*\n\n// Generate a random 'Int'\nval a: Int \u003c Sync = Random.nextInt\n\n// Generate a random 'Int' within a bound\nval b: Int \u003c Sync = Random.nextInt(42)\n\n// A few method variants\nval c: Long \u003c Sync    = Random.nextLong\nval d: Double \u003c Sync  = Random.nextDouble\nval e: Boolean \u003c Sync = Random.nextBoolean\nval f: Float \u003c Sync   = Random.nextFloat\nval g: Double \u003c Sync  = Random.nextGaussian\n\n// Obtain a random value from a sequence\nval h: Int \u003c Sync =\n    Random.nextValue(List(1, 2, 3))\n\n// Explicitly specify the `Random` implementation\nval k: Int \u003c Sync =\n    Random.let(Random.live)(h)\n```\n\n### Log: Logging\n\n`Log` is designed to streamline the logging process without requiring the instantiation of a `Logger`. Log messages automatically include source code position information (File, Line, Column), enhancing the clarity and usefulness of the logs.\n\n```scala \nimport kyo.*\n\n// Log provide trace, debug, info,\n// warn, and error method variants.\nval a: Unit \u003c Sync =\n    Log.error(\"example\")\n\n// Each variant also has a method overload\n// that takes a 'Throwable' as a second param\nval d: Unit \u003c Sync =\n    Log.error(\"example\", new Exception)\n```\n\nNote that like `Console`, `Log` methods accept `Text` values. This means they can also accept regular strings as well as outputs of `t`-interpolation ([see above](#displaying-kyo-types)).\n\n### Stat: Observability\n\n`Stat` is a pluggable implementation that provides counters, histograms, gauges, and tracing. It uses Java's [service loading](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) to locate exporters. \n\nThe module [`kyo-stats-otel`](https://central.sonatype.com/artifact/io.getkyo/kyo-stats-otel_3) provides exporters for [OpenTelemetry](https://opentelemetry.io/).\n\n```scala\nimport kyo.*\nimport kyo.stats.*\n\n// Initialize a Stat instance\n// for a scope path\nval stats: Stat =\n    Stat.initScope(\"my_application\", \"my_module\")\n\n// Initialize a counter\nval a: Counter =\n    stats.initCounter(\"my_counter\")\n\n// It's also possible to provide\n// metadata when initializing\nval b: Histogram =\n    stats.initHistogram(\n        name = \"my_histogram\",\n        description = \"some description\"\n    )\n\n// Gauges take a by-name function to\n// be observed periodically\nval c: Gauge =\n    stats.initGauge(\"free_memory\") {\n        Runtime.getRuntime().freeMemory().toDouble\n    }\n```\n\nMetrics are automatically garbage collected once no strong references to them are present anymore.\n\n\u003e Note: Although stats initialization perform side effects, Kyo chooses to consider the operation pure since stats are meant to be initialized in a static scope for optimal performance.\n\nTracing can be performed via the `traceSpan` method. It automatically initializes the span and closes it at the end of the traced computation even in the presence of failures or asynchronous operations. Nested traces are bound to their parent span via `Local`.\n\n```scala\nimport kyo.*\n\nval stats2: Stat =\n    Stat.initScope(\"my_application\", \"my_module\")\n\n// Some example computation\nval a: Int \u003c Sync =\n    Sync.defer(42)\n\n// Trace the execution of the\n// `a` example computation\nval b: Int \u003c Sync =\n    stats2.traceSpan(\"my_span\")(a)\n```\n\n### Path: File System Utilities\n\n`Path` provides utilities for interacting with the file system. It offers methods for reading, writing, and manipulating files and directories in a purely functional manner.\n\n```scala\nimport kyo.*\n\n// Create a Path instance representing a path\nval path: Path = Path(\"tmp\", \"file.txt\")\n\n// Read the entire contents of a file as a String\nval content: String \u003c Sync =\n    path.read\n\n// Write a String to a file\nval writeResult: Unit \u003c Sync =\n    path.write(\"Hello, world!\")\n\n// Check if a path exists\nval exists: Boolean \u003c Sync =\n    path.exists\n\n// Create a directory\nval createDir: Unit \u003c Sync =\n    Path(\"tmp\", \"test\").mkDir\n```\n\n`Path` instances are created by providing a list of path segments, which can be either `String`s or other `Path` instances. This allows for easy composition of paths. `Path` also provides methods for other common file operations:\n\n- Reading: `read`, `readBytes`, `readLines`, `readStream`, `readLinesStream`, `readBytesStream`\n- Writing: `write`, `writeBytes`, `writeLines`, `append`, `appendBytes`, `appendLines`\n- Directory operations: `list`, `walk`\n- File metadata: `exists`, `isDir`, `isFile`, `isLink`\n- File manipulation: `mkDir`, `mkFile`, `move`, `copy`, `remove`, `removeAll`\n\nAll methods that perform side effects are suspended using the `Sync` effect, ensuring referential transparency. Methods that work with streams of data, such as `readStream` and `walk`, return a `Stream` of the appropriate type, suspended using the `Scope` effect to ensure proper resource handling.\n\n```scala\nimport kyo.*\nimport java.io.IOException\n\nval path: Path = Path(\"tmp\", \"file.txt\")\n\n// Read a file as a stream of lines\nval lines: Stream[String, Scope \u0026 Sync] =\n    path.readLinesStream()\n\n// Process the stream\nval result: Unit \u003c (Scope \u0026 Console \u0026 Async \u0026 Abort[IOException]) =\n    lines.map(line =\u003e Console.printLine(line)).discard\n\n// Walk a directory tree\nval tree: Stream[Path, Sync] =\n    Path(\"tmp\").walk\n\n// Process each file in the tree\nval processedTree: Unit \u003c (Console \u0026 Async \u0026 Abort[IOException]) =\n    tree.map(file =\u003e file.read.map(content =\u003e Console.printLine(s\"File: ${file}, Content: $content\"))).discard\n```\n\n`Path` integrates with Kyo's `Stream` API, allowing for efficient processing of file contents using streams. The `sink` and `sinkLines` extension methods on `Stream` enable writing streams of data back to files.\n\n```scala\nimport kyo.*\n\n// Create a stream of bytes\nval bytes: Stream[Byte, Sync] = Stream.init(Seq[Byte](1, 2, 3))\n\n// Write the stream to a file\nval sinkResult: Unit \u003c (Scope \u0026 Sync) =\n    bytes.sink(Path(\"path\", \"to\", \"file.bin\"))\n```\n\n### Process: Process Execution\n\n`Process` provides a way to spawn and interact with external processes from within Kyo. It offers a purely functional interface for process creation, execution, and management.\n\n```scala\nimport kyo.*\n\n// Create a simple command\nval command: Process.Command = Process.Command(\"echo\", \"Hello, World!\")\n\n// Spawn the process and obtain the result\nval result: String \u003c Sync = command.text\n```\n\nThe core of `Process` is the `Process.Command` type, which represents a command to be executed. It can be created using the `Process.Command.apply` method, which takes a variable number of arguments representing the command and its arguments.\n\nThe `Process` object also provides a `jvm` sub-object for spawning JVM processes directly.\n\n```scala\nimport kyo.*\n\nclass MyClass extends KyoApp:\n    run {\n        Console.printLine(s\"Executed with args: $args\")\n    }\nend MyClass\n\n// Spawn a new JVM process\nval jvmProcess: Process \u003c Sync =\n    Process.jvm.spawn(classOf[MyClass], List(\"arg1\", \"arg2\"))\n```\n\nOnce a `Process.Command` is created, it can be executed using various methods:\n\n- `spawn`: Spawns the process and returns a `Process` instance.\n- `text`: Spawns the process, waits for it to complete, and returns the standard output as a string.\n- `stream`: Spawns the process and returns an `InputStream` of the standard output.\n- `exitValue`: Spawns the process, waits for it to complete, and returns the exit code.\n- `waitFor`: Spawns the process, waits for it to complete, and returns the exit code.\n\n`Process.Command` instances can be transformed and combined using methods like `pipe`, `andThen`, `+`, `map`, and `cwd`, `env`, `stdin`, `stdout`, `stderr` for modifying the process's properties.\n\n```scala\nimport java.io.File\nimport java.nio.file.Path\nimport kyo.*\n\n// Create a piped command\nval pipedCommand = Process.Command(\"echo\", \"Hello, World!\").pipe(Process.Command(\"wc\", \"-w\"))\n\n// Modify the command's environment and working directory\nval modifiedCommand = pipedCommand.env(Map(\"VAR\" -\u003e \"value\")).cwd(Path.of(\"/path/to/dir\"))\n\n// Spawn the modified command\nval modifiedResult: String \u003c Sync = modifiedCommand.text\n```\n\n`Process` also provides `Input` and `Output` types for fine-grained control over the process's standard input, output, and error streams.\n\n```scala\nimport java.io.File\nimport kyo.*\n\n// Create a command with custom input and output\nval command = Process.Command(\"my-command\")\n    .stdin(Process.Input.fromString(\"input data\"))\n    .stdout(Process.Output.FileRedirect(new File(\"output.txt\")))\n    .stderr(Process.Output.Inherit)\n```\n\nThe `Process` type returned by `spawn` provides methods for interacting with the spawned process, such as `waitFor`, `exitValue`, `destroy`, and `isAlive`.\n\n### Parse: Syntactic and lexical analysis\n\n`Parse` provides a way to transform a sequence of tokens (typically chars if the input is textual) into data structures such as an AST by doing lexical/syntactic analysis. `Parse` provides many combinators to build complex parsers upon basic ones.\n\n```scala\nimport kyo.*\n\ndef term: Int \u003c Parse[Char] =\n    Parse.firstOf(\n        Parse.int,\n        Parse.between(\n            Parse.literal('('),\n            expr,\n            Parse.literal(')')\n        )\n    )\n\ndef expr: Int \u003c Parse[Char] =\n    Parse.firstOf(\n        for\n            left  \u003c- term\n            _     \u003c- Parse.require(Parse.literal('+'))\n            right \u003c- expr\n        yield left + right,\n        term\n    )\n\nval parser: Int \u003c Parse[Char] = Parse.entireInput(expr)\n\nParse.runResult(\"1\")(parser)       // 1\nParse.runResult(\"1+2\")(parser)     // 3\nParse.runResult(\"1+(4+5)\")(parser) // 10\nParse.runResult(\"1*2\")(parser)     // Error: Expected: +, Got: * at position 1\n```\n\nUnlike most parsing combinators libraries, Kyo's `Parse` provides ways to accumulate errors and recover from them.\n\n```scala\nimport kyo.*\n\nval array: Chunk[Int] \u003c Parse[Char] = Parse.entireInput(\n    Parse.between(\n        Parse.literal('['),\n        Parse.separatedBy(\n            Parse.recoverWith(\n                Parse.int,\n                RecoverStrategy.skipThenRetryUntil(Parse.any, Parse.literal(','))\n            ),\n            Parse.literal(',')\n        ),\n        Parse.literal(']')\n    )\n)\n\nParse.runResult(\"[]\")(array)      // Chunk()\nParse.runResult(\"[1,2,3]\")(array) // Chunk(1, 2, 3)\n\n/*\nErrors:\n- Invalid int at position 1\n- Invalid int at position 5\n\nRecovered result: Chunk(2, 4)\n*/\nParse.runResult(\"[a,2,c,4]\")(array)\n```\n\n`Parse.runResult` returns a `ParseResult` which contains both errors and a `Maybe` of the result. Note that it is possible to have both errors and an output in the case of a recovered output like in the last example.\n\n`Parse` also provides `runOrAbort` to abort if the parsing was, entirely or partially, unsuccessful.\n\n```scala mdoc:nest\nAbort.run(Parse.runOrAbort(\"[1,2,3]\")(array)) //Chunk(1, 2, 3)\nAbort.run(Parse.runOrAbort(\"[1,a,3]\")(array)) //Failure\n\narray.handle(\n    Parse.runOrAbort(\"[1,2,3]\"),\n    Abort.run\n) //Chunk(1, 2, 3)\n```\n\n## Concurrent Effects\n\nThe kyo-core module provides utilities for dealing with concurrency in Scala applications. It's a powerful set of effects designed for easier asynchronous programming, built on top of other core functionalities provided by the `kyo` package.\n\n### Async: Green Threads\n\nThe `Async` effect allows for the asynchronous execution of computations via a managed thread pool. The core combinators, such as `foreach`, spawns a number of new \"green threads\", also known as 'Fiber's, to handle the given computations. This provides a powerful mechanism for parallel execution and efficient use of system resources. Moreover, fibers maintain proper propagation of `Local`, ensuring that context information is carried along during the forking process.\n\n```scala\nimport kyo.*\n\n// Fork a computation. The parameter is\n// taken by reference and automatically\n// suspended with 'Sync'\nval a: Fiber[Int, Any] \u003c Sync =\n    Fiber.initUnscoped(Math.cos(42).toInt)\n\n// It's possible to \"extract\" the value of a\n// 'Fiber' via the 'get' method. This is also\n// referred as \"joining the fiber\"\nval b: Int \u003c Async =\n    a.map(_.get)\n```\n\nThe `zip` and `collectAll` methods fork multiple computations concurrently, join the fibers, and return their results.\n\n```scala\nimport kyo.*\n\n// An example computation\nval a: Int \u003c Sync =\n    Sync.defer(Math.cos(42).toInt)\n\n// There are method overloadings for up to four\n// parallel computations. Parameters taken by\n// reference\nval b: (Int, String) \u003c Async =\n    Async.zip(a, \"example\")\n\n// Run with unlimited concurrency - starts all\n// computations immediately\nval c: Seq[Int] \u003c Async =\n    Async.collectAll(Seq(a, a.map(_ + 1)))\n\n// Run with controlled concurrency (max 2 tasks)\nval d: Seq[Int] \u003c Async =\n    Async.collectAll(Seq(a, a.map(_ + 1)), concurrency = 2)\n\n```\n\nIf any computation fails or is interrupted, all other computations are automatically interrupted.\n\nThe `race` methods are similar to `parallel` but they return the first computation to complete with either a successful result or a failure. Once the first result is produced, the other computations are automatically interrupted.\n\n```scala\nimport kyo.*\n\n// An example computation\nval a: Int \u003c Sync =\n    Sync.defer(Math.cos(42).toInt)\n\n// There are method overloadings for up to four\n// computations. Parameters taken by reference\nval b: Int \u003c Async =\n    Async.race(a, a.map(_ + 1))\n\n// It's also possible to to provide a 'Seq'\n// of computations\nval c: Int \u003c Async =\n    Async.race(Seq(a, a.map(_ + 1)))\n```\n\nThe `sleep` and `timeout` methods pause a computation or time it out after a duration.\n\n```scala\nimport kyo.*\n\n// A computation that sleeps for 1s\nval a: Unit \u003c Async =\n    Async.sleep(1.second)\n\n// Times out and interrupts the provided\n// computation in case it doesn't produce\n// a result within 1s\nval b: Int \u003c (Abort[Timeout] \u0026 Async) =\n    Async.timeout(1.second)(Math.cos(42).toInt)\n```\n\nThe `fromFuture` method provide interoperability with Scala's `Future`.\n\n```scala\nimport kyo.*\nimport scala.concurrent.Future\n\n// An example 'Future' instance\nval a: Future[Int] = Future.successful(42)\n\n// Transform a 'Future' into a 'Fiber'\nval b: Fiber[Int, Any] \u003c Sync =\n    Fiber.fromFuture(a)\n```\n\n\u003e Important: Keep in mind that Scala's Future lacks built-in support for interruption. As a result, any computations executed through Future will run to completion, even if they're involved in a race operation where another computation finishes first.\n\nA `Fiber` instance also provides a few relevant methods.\n\n```scala\nimport kyo.*\nimport scala.concurrent.*\n\n// An example fiber\nval a: Fiber[Int, Any] = Fiber.succeed(42)\n\n// Check if the fiber is done\nval b: Boolean \u003c Sync =\n    a.done\n\n// Instance-level version of 'Async.get'\nval c: Int \u003c Async =\n    a.get\n\n// Avoid this low-level API to attach a\n// a callback to a fiber\nval d: Unit \u003c Sync =\n    a.onComplete(println(_))\n\n// A variant of `get` that returns a `Result`\n// with the failed or successful result\nval e: Result[Nothing, Int] \u003c Async =\n    a.getResult\n\n// Try to interrupt/cancel a fiber\nval f: Boolean \u003c Sync =\n    a.interrupt\n\n// Transforms a fiber into a Scala 'Future'\nval h: Future[Int] \u003c Sync =\n    a.toFuture\n\n// 'Fiber' provides a monadic API with both\n// 'map' and 'flatMap'\nval i: Fiber[Int, Any] \u003c Sync =\n    a.flatMap(v =\u003e Fiber.succeed(v.eval + 1))\n```\n\nSimilarly to `Sync`, users should avoid handling the `Async` effect directly and rely on `KyoApp` instead. If strictly necessary, there are two methods to handle the `Async` effect:\n\n1. `run` takes a computation that has only the `Async` effect pending and returns a `Fiber` instance without blocking threads.\n2. `runAndBlock` accepts computations with arbitrary pending effects but it handles asynchronous operations by blocking the current thread.\n\n```scala\nimport kyo.*\n\n// An example computation with fibers\nval a: Int \u003c Async =\n    Fiber.initUnscoped(Math.cos(42).toInt).map(_.get)\n\n// Avoid handling 'Async' directly\nval b: Fiber[Int, Any] \u003c Sync =\n    Fiber.initUnscoped(a)\n\n// The 'runAndBlock' method accepts\n// arbitrary pending effects but relies\n// on thread blocking and requires a timeout\nval c: Int \u003c (Abort[Timeout] \u0026 Sync) =\n    KyoApp.runAndBlock(5.seconds)(a)\n```\n\n\u003e Note: Handling the `Async` effect doesn't break referential transparency as with `Sync` but its usage is not trivial due to the limitations of the pending effects. Prefer `KyoApp` instead.\n\nThe `Async` effect also offers a low-level API to create `Promise`s as way to integrate external async operations with fibers. These APIs should be used only in low-level integration code.\n\n```scala\nimport kyo.*\n\n// Initialize a promise\nval a: Promise[Int, Any] \u003c Sync =\n    Promise.init[Int, Any]\n\n// Try to fulfill a promise\nval b: Boolean \u003c Sync =\n    a.map(_.complete(Result.succeed(42)))\n\n// Fullfil the promise with\n// another fiber\nval c: Boolean \u003c Sync =\n    a.map(fiber =\u003e Fiber.initUnscoped(1).map(fiber.become(_)))\n```\n\n\u003e A `Promise` is basically a `Fiber` with all the regular functionality plus the `complete` and `become` methods to manually fulfill the promise.\n\n## Retry: Automatic Retries\n\n`Retry` provides a mechanism for retrying computations that may fail, with configurable policies for backoff and retry limits. This is particularly useful for operations that might fail due to transient issues, such as network requests or database operations.\n\n```scala\nimport kyo.*\nimport scala.concurrent.duration.*\n\n// Define a computation that might fail\nval unreliableComputation: Int \u003c Abort[Exception] =\n    Abort.catching[Exception](throw new Exception(\"Temporary failure\"))\n\n// Customize retry schedule\nval schedule = \n    Schedule.exponentialBackoff(initial = 100.millis, factor = 2, maxBackoff = 5.seconds)\n        .take(5)\n\nval a: Int \u003c (Abort[Exception] \u0026 Async) =\n    Retry[Exception](schedule)(unreliableComputation)\n\n```\n\nThe `Retry` effect automatically adds the `Async` effect to handle the provided `Schedule`. `Retry` will continue attempting the computation until it succeeds, the retry schedule is done, or an unhandled exception is thrown. If all retries fail, the last failure is propagated.\n\n### Queue: Concurrent Queuing\n\nThe `Queue` effect operates atop of `Sync` and provides thread-safe queue data structures based on the high-performance [JCTools](https://github.com/JCTools/JCTools) library on the JVM. For ScalaJS, a simple `ArrayQueue` is used.\n\n\u003e Warning: The actual capacity of a `Queue` is rounded up to the next power of two for performance reasons. For example, if you specify a capacity of `10`, the actual capacity will be `16`.\n\n**Bounded queues**\n```scala\nimport kyo.*\n\n// A bounded queue that rejects new\n// elements once full\nval a: Queue[Int] \u003c (Sync \u0026 Scope) =\n    Queue.init(capacity = 42)\n\n// Obtain the number of items in the queue\n// via the method 'size' in 'Queue'\nval b: Int \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.size)\n\n// Get the queue capacity\nval c: Int \u003c (Sync \u0026 Scope) =\n    a.map(_.capacity)\n\n// Try to offer a new item\nval d: Boolean \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.offer(42))\n\n// Try to poll an item\nval e: Maybe[Int] \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.poll)\n\n// Try to 'peek' an item without removing it\nval f: Maybe[Int] \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.peek)\n\n// Check if the queue is empty\nval g: Boolean \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.empty)\n\n// Check if the queue is full\nval h: Boolean \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.full)\n\n// Drain the queue items\nval i: Seq[Int] \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.drain)\n\n// Close the queue. If successful,\n// returns a Some with the drained\n// elements\nval j: Maybe[Seq[Int]] \u003c (Sync \u0026 Scope) =\n    a.map(_.close)\n```\n\n**Unbounded queues**\n```scala\nimport kyo.*\n\n// Avoid `Queue.unbounded` since if queues can\n// grow without limits, the GC overhead can make\n// the system fail\nval a: Queue.Unbounded[Int] \u003c (Sync \u0026 Scope) =\n    Queue.Unbounded.init()\n\n// A 'dropping' queue discards new entries\n// when full\nval b: Queue.Unbounded[Int] \u003c (Sync \u0026 Scope) =\n    Queue.Unbounded.initDropping(capacity = 42)\n\n// A 'sliding' queue discards the oldest\n// entries if necessary to make space for new\n// entries\nval c: Queue.Unbounded[Int] \u003c (Sync \u0026 Scope) =\n    Queue.Unbounded.initSliding(capacity = 42)\n\n// Note how 'dropping' and 'sliding' queues\n// return 'Queue.Unbounded`. It provides\n// an additional method to 'add' new items\n// unconditionally\nval d: Unit \u003c (Sync \u0026 Scope) =\n    c.map(_.add(42))\n```\n\n**Concurrent Access Policies**\n\nIt's also possible to specify a concurrent `Access` policy as the second parameter of the `Queue.init` methods. This configuration has an effect only on the JVM and is ignored in ScalaJS.\n\n| Policy                       | Full Form                              | Description                                                                                                                                                                                                          |\n| ---------------------------- | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| MultiProducerMultiConsumer   | Multiple Producers, Multiple Consumers | Supports multiple threads/fibers simultaneously enqueuing and dequeuing elements. This is the most flexible but may incur the most overhead due to the need to synchronize between multiple producers and consumers. |\n| MultiProducerSingleConsumer  | Multiple Producers, Single Consumer    | Allows multiple threads/fibers to enqueue elements but restricts dequeuing to a single consumer. This can be more efficient than `Mpmc` when only one consumer is needed.                                            |\n| SingleProducerMultiConsumer  | Single Producer, Multiple Consumers    | Allows only a single thread/fiber to enqueue elements, but multiple threads/fibers can dequeue elements. Useful when only one source is generating elements to be processed by multiple consumers.                   |\n| SingleProducerSingleConsumer | Single Producer, Single Consumer       | The most restrictive but potentially fastest policy. Only one thread/fiber can enqueue elements, and only one thread/fiber can dequeue elements.                                                                     |\n\nEach policy is suitable for different scenario and comes with its own trade-offs. For example, `Mpmc` is highly flexible but can be slower due to the need for more complex synchronization. `Spsc`, being the most restrictive, allows for optimizations that could make it faster for specific single-producer, single-consumer scenario.\n\nYou can specify the access policy when initializing a queue, and it is important to choose the one that aligns with your application's needs for optimal performance.\n\n```scala\nimport kyo.*\n\n// Initialize a bounded queue with a\n// Multiple Producers, Multiple\n// Consumers policy\nval a: Queue[Int] \u003c (Sync \u0026 Scope) =\n    Queue.init(\n        capacity = 42,\n        access = Access.MultiProducerMultiConsumer\n    )\n```\n\n### Channel: Backpressured Communication\n\nThe `Channel` effect serves as an advanced concurrency primitive, designed to facilitate seamless and backpressured data transfer between various parts of your application. Built upon the `Async` effect, `Channel` not only ensures thread-safe communication but also incorporates a backpressure mechanism. This mechanism temporarily suspends fibers under specific conditions—either when waiting for new items to arrive or when awaiting space to add new items.\n\n\u003e Warning: The actual capacity of a `Channel` is rounded up to the next power of two for performance reasons. For example, if you specify a capacity of `10`, the actual capacity will be `16`.\n\n```scala    \nimport kyo.*\n\n// A 'Channel' is initialized with a fixed capacity\n// Note the `Resource` effect, which ensures the channel\n// will eventually be closed\nval a: Channel[Int] \u003c (Sync \u0026 Scope) =\n    Channel.init(capacity = 42)\n\n// It's also possible to specify\n// an 'Access' policy\nval b: Channel[Int] \u003c (Sync \u0026 Scope) =\n    Channel.init(\n        capacity = 42,\n        access = Access.MultiProducerMultiConsumer\n    )\n```\n\nWhile `Channel` share similarities with `Queue`—such as methods for querying size (`size`), adding an item (`offer`), or retrieving an item (`poll`)—they go a step further by offering backpressure-sensitive methods, namely `put` and `take`.\n\n```scala\nimport kyo.*\n\n// An example channel\nval a: Channel[Int] \u003c (Sync \u0026 Scope) =\n    Channel.init(capacity = 42)\n\n// Adds a new item to the channel.\n// If there's no capacity, the fiber\n// is automatically suspended until\n// space is made available\nval b: Unit \u003c (Async \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.put(42))\n\n// Takes an item from the channel.\n// If the channel is empty, the fiber\n// is suspended until a new item is\n// made available\nval c: Int \u003c (Async \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.take)\n\n// Closes the channel. If successful,\n// returns a Some with the drained\n// elements. All pending puts and takes\n// are automatically interrupted\nval f: Maybe[Seq[Int]] \u003c (Sync \u0026 Scope) =\n    a.map(_.close)\n```\n\nThe ability to suspend fibers during `put` and `take` operations allows `Channel` to provide a more controlled form of concurrency. This is particularly beneficial for rate-sensitive or resource-intensive tasks where maintaining system balance is crucial.\n\n\u003e Important: While a `Channel` comes with a predefined capacity, it's crucial to understand that there is no upper limit on the number of fibers that can be suspended by it. In scenario where your application spawns an unrestricted number of fibers—such as an HTTP service where each incoming request initiates a new fiber—this can lead to significant memory consumption. The channel's internal queue for suspended fibers could grow indefinitely, making it a potential source of unbounded queuing and memory issues. Exercise caution in such use-cases to prevent resource exhaustion.\n\n### Hub: Broadcasting with Backpressure\n\n`Hub` provide a broadcasting mechanism where messages are sent to multiple listeners simultaneously. They are similar to `Channel`, but they are uniquely designed for scenario involving multiple consumers. The key feature of `Hub` is their ability to apply backpressure automatically. This means if the `Hub` and any of its listeners' buffers are full, the `Hub` will pause both the producers and consumers to prevent overwhelming the system. Unlike `Channel`, `Hub` don't offer customization in concurrent access policy as they are inherently meant for multi-producer, multi-consumer environments.\n\n```scala\nimport kyo.*\nimport kyo.Hub.Listener\n\n// Initialize a Hub with a buffer\nval a: Hub[Int] \u003c (Sync \u0026 Scope) =\n    Hub.init[Int](3)\n\n// Hub provide APIs similar to\n// channels: size, offer, isEmpty,\n// isFull, put\nval b: Boolean \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.offer(1))\n\n// But reading from hubs can only\n// happen via listener. Listeners\n// only receive messages sent after\n// their creation. To create call\n// `listen`:\nval c: Listener[Int] \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.listen)\n\n// Each listener can have an\n// additional message buffer\nval d: Listener[Int] \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.listen(bufferSize = 3))\n\n// Listeners provide methods for\n// receiving messages similar to\n// channels: size, isEmpty, isFull,\n// poll, take\nval e: Int \u003c (Async \u0026 Abort[Closed] \u0026 Scope) =\n    d.map(_.take)\n\n// A listener can be closed\n// individually. If successful,\n// a Some with the backlog of\n// pending messages is returned\nval f: Maybe[Seq[Int]] \u003c (Sync \u0026 Abort[Closed] \u0026 Scope) =\n    d.map(_.close)\n\n// Listeners are also managed\n// resources. They are closed \n// when their `Resource` effect\n// is handled\nval g: Int \u003c (Async \u0026 Abort[Closed]) =\n    Scope.run(e)\n\n// If the Hub is closed, all\n// listeners are automatically\n// closed. The returned backlog\n// only include items pending in\n// the hub's buffer. The listener\n// buffers are discarded\nval h: Maybe[Seq[Int]] \u003c (Sync \u0026 Scope) =\n    a.map(_.close)\n```\n\nHub are implemented with an internal structure that efficiently manages message distribution. At their core, Hub utilize a single channel for incoming messages. This central channel acts as the primary point for all incoming data. For each listener attached to a Hub, a separate channel is created. These individual channels are dedicated to each listener, ensuring that messages are distributed appropriately.\n\nThe functioning of Hub is orchestrated by a dedicated fiber. This fiber continuously monitors the main incoming channel. Whenever a new message arrives, it takes this message and concurrently distributes it to all the listener channels. This process involves submitting the message to each listener's channel in parallel, ensuring simultaneous delivery of messages.\n\nAfter distributing a message, the fiber waits until all the listener channels have successfully received it. This waiting mechanism is crucial for maintaining the integrity of message distribution, ensuring that each listener gets the message before the fiber proceeds to the next one and backpressure is properly applied.\n\n### Meter: Computational Limits\n\nThe `Meter` effect offers utilities to regulate computational execution, be it limiting concurrency or managing rate. It is equipped with a range of pre-set limitations, including mutexes, semaphores, and rate limiters, allowing you to apply fine-grained control over task execution.\n\n```scala\nimport kyo.*\n\n// 'mutex': One computation at a time\nval a: Meter \u003c (Sync \u0026 Scope) =\n    Meter.initMutex\n\n// 'semaphore': Limit concurrent tasks\nval b: Meter \u003c (Sync \u0026 Scope) =\n    Meter.initSemaphore(concurrency = 42)\n\n// 'rateLimiter': Tasks per time window\nval c: Meter \u003c (Sync \u0026 Scope) =\n    Meter.initRateLimiter(\n        rate = 10,\n        period = 1.second\n    )\n\n// 'pipeline': Combine multiple 'Meter's\nval d: Meter \u003c (Sync \u0026 Scope) =\n    Meter.pipeline(a, b, c)\n```\n\nThe `Meter` class comes with a handful of methods designed to provide insights into and control over computational execution.\n\n```scala\nimport kyo.*\n\n// An example 'Meter'\nval a: Meter \u003c (Sync \u0026 Scope) =\n    Meter.initMutex\n\n// Get the number available permits\nval b: Int \u003c (Async \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.availablePermits)\n\n// Get the number of waiting fibers\nval c: Int \u003c (Async \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.pendingWaiters)\n\n// Use 'run' to execute tasks\n// respecting meter limits\nval d: Int \u003c (Async \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.run(Math.cos(42).toInt))\n\n// 'tryRun' executes if a permit is\n// available; returns 'None' otherwise\nval e: Maybe[Int] \u003c (Async \u0026 Abort[Closed] \u0026 Scope) =\n    a.map(_.tryRun(Math.cos(42).toInt))\n```\n\n### Latch: Countdown Synchronization\n\nThe `Latch` effect serves as a coordination mechanism for fibers in a concurrent environment, primarily used for task synchronization. It provides a low-level API for controlling the flow of execution and ensuring certain tasks are completed before others, all while maintaining thread safety.\n\n```scala\nimport kyo.*\n\n// Initialize a latch with 'n' permits\nval a: Latch \u003c Sync =\n    Latch.init(3)\n\n// Await until the latch releases\nval b: Unit \u003c Async =\n    a.map(_.await)\n\n// Release a permit from the latch\nval c: Unit \u003c Sync =\n    a.map(_.release)\n\n// Get the number of pending permits\nval d: Int \u003c Sync =\n    a.map(_.pending)\n```\n\n### Barrier: Multi-party Rendezvous\n\nThe `Barrier` effect provides a synchronization primitive that allows a fixed number of parties to wait for each other to reach a common point of execution. It's particularly useful in scenarios where multiple fibers need to synchronize their progress.\n\n```scala\nimport kyo.*\n\n// Initialize a barrier for 3 parties\nval a: Barrier \u003c Sync =\n    Barrier.init(3)\n\n// Wait for the barrier to be released\nval b: Unit \u003c Async =\n    a.map(_.await)\n\n// Get the number of parties still waiting\nval c: Int \u003c Sync =\n    a.map(_.pending)\n\n// Example usage with multiple fibers\nval d: Unit \u003c Async =\n    for\n        barrier \u003c- Barrier.init(3)\n        _       \u003c- Async.zip(\n                     barrier.await,\n                     barrier.await,\n                     barrier.await\n                   )\n    yield ()\n\n// Fibers can join the barrier at different points of the computation\nval e: Unit \u003c Async =\n    for\n        barrier \u003c- Barrier.init(3)\n        fiber1  \u003c- Fiber.initUnscoped(Async.sleep(1.second))\n        fiber2  \u003c- Fiber.initUnscoped(Async.sleep(2.seconds))\n        _       \u003c- Async.zip(\n                     fiber1.get.map(_ =\u003e barrier.await),\n                     fiber2.get.map(_ =\u003e barrier.await),\n                     Fiber.initUnscoped(barrier.await).map(_.get)\n                   )\n    yield ()\n```\n\nThe `Barrier` is initialized with a specific number of parties. Each party calls `await` when it reaches the barrier point. The barrier releases all waiting parties when the last party arrives. After all parties have been released, the barrier cannot be reset or reused.\n\n### Atomic: Concurrent State\n\nThe `Atomic` effect provides a set of thread-safe atomic variables to manage mutable state in a concurrent setting. Available atomic types include Int, Long, Boolean, and generic references.\n\n```scala\nimport kyo.*\n\n// Initialize atomic variables\nval aInt: AtomicInt \u003c Sync =\n    AtomicInt.init(0)\nval aLong: AtomicLong \u003c Sync =\n    AtomicLong.init(0L)\nval aBool: AtomicBoolean \u003c Sync =\n    AtomicBoolean.init(false)\nval aRef: AtomicRef[String] \u003c Sync =\n    AtomicRef.init(\"initial\")\n\n// Fetch values\nval b: Int \u003c Sync =\n    aInt.map(_.get)\nval c: Long \u003c Sync =\n    aLong.map(_.get)\nval d: Boolean \u003c Sync =\n    aBool.map(_.get)\nval e: String \u003c Sync =\n    aRef.map(_.get)\n\n// Update values\nval f: Unit \u003c Sync =\n    aInt.map(_.set(1))\nval g: Unit \u003c Sync =\n    aLong.map(_.lazySet(1L))\nval h: Boolean \u003c Sync =\n    aBool.map(_.compareAndSet(false, true))\nval i: String \u003c Sync =\n    aRef.map(_.getAndSet(\"new\"))\n```\n\n### Adder: Concurrent Accumulation\n\nThe `Adder` effect offers thread-safe variables for efficiently accumulating numeric values. The two primary classes, `LongAdder` and `DoubleAdder`, are optimized for high-throughput scenario where multiple threads update the same counter.\n\n```scala\nimport kyo.*\n\n// Initialize Adder\nval longAdder: LongAdder \u003c Sync =\n    LongAdder.init\nval doubleAdder: DoubleAdder \u003c Sync =\n    DoubleAdder.init\n\n// Adding values\nval a: Unit \u003c Sync =\n    longAdder.map(_.add(10L))\nval b: Unit \u003c Sync =\n    doubleAdder.map(_.add(10.5))\n\n// Increment and Decrement LongAdder\nval c: Unit \u003c Sync =\n    longAdder.map(_.increment)\nval d: Unit \u003c Sync =\n    longAdder.map(_.decrement)\n\n// Fetch summed values\nval e: Long \u003c Sync =\n    longAdder.map(_.get)\nval f: Double \u003c Sync =\n    doubleAdder.map(_.get)\n\n// Resetting the adders\nval g: Unit \u003c Sync =\n    longAdder.map(_.reset)\nval h: Unit \u003c Sync =\n    doubleAdder.map(_.reset)\n```\n\n### Debug: Interactive Development\n\nThe `Debug` effect is a powerful tool for developers during the development process. Unlike other effects in Kyo, `Debug` intentionally performs side effects (printing to the console) without effect suspensions to provide immediate, visible feedback to developers. This makes it a valuable tool for debugging and understanding code behavior, but it's crucial to use it only in development environments and remove it before moving to production.\n\n```scala\nimport kyo.*\n\n// Note that 'Debug' requires a separate import\nimport kyo.debug.*\n\n// Wraps a computation, printing the source code location,\n// and the result (or exception) of the computation\nval a: Int \u003c Sync =\n    Debug {\n        Sync.defer(42)\n    }\n\n// Similar to `apply`, but also prints intermediate steps\n// of the computation, providing a trace of execution\nval b: Int \u003c Sync =\n    Debug.trace {\n        Sync.defer(41).map(_ + 1)\n    }\n\n// Allows printing of specific values along with their \n// variable names, useful for inspecting particular states.\n// The return type of 'values' is 'Unit', not an effectful\n// computation.\nval c: Unit \u003c Sync =\n    Sync.defer {\n        val x = 42\n        val y = \"Hello\"\n        Debug.values(x, y)\n    }\n```\n\n## Data Types\n\n### Maybe: Allocation-free Optional Values\n\n`Maybe` provides an allocation-free alternative to Scala's standard `Option` type. It is designed to be a drop-in replacement for `Option`, offering similar functionality while minimizing memory allocation.\n\n```scala\nimport kyo._\n\n// Create a 'Maybe' value\nval a: Maybe[Int] = Maybe(42)\n\n// 'Absent' represents the absence of a value\nval b: Maybe[Int] = Absent\n\n// 'Maybe.when' conditionally creates a 'Maybe' value\nval c: Maybe[Int] = Maybe.when(true)(42)\n\n// 'Maybe.fromOption' converts an 'Option' to a 'Maybe'\nval d: Maybe[Int] = Maybe.fromOption(Some(42))\n\n// 'isEmpty' checks if the 'Maybe' is empty\nval e: Boolean = a.isEmpty\n\n// 'isDefined' checks if the 'Maybe' has a value\nval f: Boolean = a.isDefined\n\n// 'get' retrieves the value, throwing if empty\nval g: Int = a.get\n\n// 'getOrElse' provides a default value if empty\nval h: Int = b.getOrElse(0)\n\n// 'fold' applies a function based on emptiness\nval i: String = a.fold(\"Empty\")(_.toString)\n\n// 'map' transforms the value if present\nval j: Maybe[String] = a.map(_.toString)\n\n// 'flatMap' allows chaining 'Maybe' operations\nval k: Maybe[Int] = a.flatMap(v =\u003e Maybe(v + 1))\n\n// 'filter' conditionally keeps or discards the value\nval l: Maybe[Int] = a.filter(_ \u003e 0)\n\n// 'contains' checks if the 'Maybe' contains a value\nval m: Boolean = a.contains(42)\n\n// 'exists' checks if a predicate holds for the value\nval n: Boolean = a.exists(_ \u003e 0)\n\n// 'foreach' applies a side-effecting function if non-empty\na.foreach(println)\n\n// 'collect' applies a partial function if defined\nval o: Maybe[String] = a.collect { case 42 =\u003e \"forty-two\" }\n\n// 'orElse' returns an alternative if empty\nval p: Maybe[Int] = b.orElse(Maybe(0))\n\n// 'zip' combines two 'Maybe' values into a tuple\nval q: Maybe[(Int, String)] = a.zip(Maybe(\"hello\"))\n\n// 'toOption' converts a 'Maybe' to an 'Option'\nval r: Option[Int] = a.toOption\n\n// Using 'Maybe' in a for-comprehension\nval s: Maybe[Int] = for {\n  x \u003c- Maybe(1)\n  y \u003c- Maybe(2)\n  if x \u003c y\n} yield x + y\n\n// Nesting 'Maybe' values\nval nested: Maybe[Maybe[Int]] = Maybe(Maybe(42))\nval flattened: Maybe[Int] = nested.flatten\n\n// Pattern matching with 'Present' and 'Absent'\nval result: String = \n    flattened match\n        case Present(value) =\u003e s\"Value: $value\"\n        case Absent        =\u003e \"No value\"\n```\n\n`Maybe`'s high performance is due to the fact that it is unboxed. Accordingly, we recommend using t-string interpolation when logging `Maybe`s:\n\n```scala\nimport kyo.*\n\nval maybe: Maybe[Maybe[Int]] = Maybe(Maybe(42))\nval maybeNot: Maybe[Maybe[Int]] = Maybe(Maybe.Absent)\n\nprintln(s\"s-string nested maybes: $maybe, $maybeNot\")\n// Output: s-string nested maybes: 42, Absent\n\nprintln(t\"t-string nested maybes: $maybe, $maybeNot\")\n// Output: t-string nested maybes: Present(Present(42)), Present(Absent)\n```\n\n### Duration: Time Representation\n\n`Duration` provides a convenient and efficient way to represent and manipulate time durations. It offers a wide range of operations and conversions, making it easy to work with time intervals in various units.\n\n```scala\nimport kyo.*\nimport kyo.Duration.Units.*\n\n// Create durations using convenient extension methods\nval a: Duration = 5.seconds\nval b: Duration = 100.millis\nval c: Duration = 1.hour\n\n// Perform arithmetic operations\nval d: Duration = a + b\nval e: Duration = c * 2\n\n// Compare durations\nval f: Boolean = a \u003e b\nval g: Boolean = c \u003c= 60.minutes\n\n// Convert to different time units\nval h: Long = c.toMinutes // 60\nval i: Long = a.toMillis  // 5000\n\n// Create durations from various units\nval j: Duration = Duration.fromNanos(1000000)\nval k: Duration = Duration.fromUnits(2, Weeks)\n\n// Convert to and from Java and Scala durations\nimport java.time.Duration as JavaDuration\nimport scala.concurrent.duration.Duration as ScalaDuration\n\nval l: Duration = Duration.fromJava(JavaDuration.ofSeconds(30))\nval m: Duration = Duration.fromScala(ScalaDuration(1, \"day\"))\n\nval n: JavaDuration = c.toJava\nval o: ScalaDuration = b.toScala\n\n// Special durations\nval p: Duration = Duration.Zero\nval q: Duration = Duration.Infinity\n\n// Render duration as a string\nval r: String = a.show // \"Duration(5000000000 ns)\"\n```\n\n`Duration` is implemented as an `opaque type` alias for `Long`, representing nanoseconds internally. This design ensures type safety while maintaining high performance.\n\n### Result: Typed Failure Handling\n\n`Result` is a type that combines features of Scala's `Try` and `Either` types, designed to represent the result of a computation that may either succeed with a value or fail with an exception. It provides a flexible way to handle both successful outcomes and typed failures.\n\n```scala\nimport kyo._\nimport scala.util.Try\n\n// Create a 'Result' from a value\nval a: Result[Nothing, Int] = Result.succeed(42)\n\n// Create a 'Result' from an failure\nval b: Result[Exception, Int] = Result.fail(new Exception(\"Oops\"))\n\n// Use 'apply' to create a 'Result' from a block of code\nval c: Result[Nothing, Int] = Result(42 / 0)\n\n// 'isSuccess' checks if the 'Result' is a success\nval d: Boolean = a.isSuccess\n\n// 'isFail' checks if the 'Result' is a failure\nval e: Boolean = b.isFailure\n\n// 'get' retrieves the value if successful, otherwise throws\nval f: Int = a.getOrThrow\n\n// 'getOrElse' provides a default value for failures\nval g: Int = b.getOrElse(0)\n\n// 'foldError' applies a function based on success or failure\nval h: String = a.foldError(_.toString, e =\u003e \"failure \" + e)\n\n// 'map' transforms the value if successful\nval i: Result[Nothing, String] = a.map(_.toString)\n\n// 'flatMap' allows chaining 'Result' operations\nval j: Result[Nothing, Int] = a.flatMap(v =\u003e Result.succeed(v + 1))\n\n// 'flatten' removes one level of nesting from a 'Result[Result[T]]'\nval k: Result[Nothing, Result[Nothing, Int]] = Result.succeed(a)\nval l: Result[Nothing, Int] = k.flatten\n\n// 'filter' conditionally keeps or discards the value\nval m: Result[NoSuchElementException, Int] = a.filter(_ \u003e 0)\n\n// 'mapFailure' allows mapping failures \nval n: Result[Int, Int] = b.mapFailure { _ =\u003e 0 }\n\n// 'flatMapFailure' allows handling failures with a function returning a 'Result'\nval o: Result[Nothing, Int] = b.flatMapFailure { case _ =\u003e Result.succeed(0) }\n\n// 'toEither' converts a 'Result' to an 'Either'\nval p: Either[Throwable, Int] = a.toEither\n\n// 'toTry' converts a 'Result' to a 'Try'\nval q: Try[Int] = a.toTry\n```\n\nUnder the hood, `Result` is defined as an opaque type that is a supertype of `Success[T]` and `Failure[T]`. Success[T] represents a successful result and is encoded as either the value itself (`T`) or a special SuccessFailure[`T`] case class. The `SuccessFailure[T]` case class is used to handle the rare case where a `Failure[T]` needs to be wrapped in a `Success[T]`. On the other hand, a failed `Result` is always represented by a `Failure[T]` case class, which contains the exception that caused the failure. This means that creating a `Failure[T]` does incur an allocation cost. Additionally, some methods on `Result`, such as `fold`, `map`, and `flatMap`, may allocate in certain cases due to the need to catch and handle exceptions.\n\nSince `Result.Success` is unboxed, we recommend using t-string interpolation when logging `Result`s:\n\n```scala\nimport kyo.*\n\nval success: Result[String, Result[String, Int]] = Result.succeed(Result.succeed(42))\nval failure: Result[String, Result[String, Int]] = Result.succeed(Result.fail(\"failure!\"))\n\nprintln(s\"s-string nested results: $success, $failure\")\n// Output: s-string nested results: 42, Fail(failure!)\n\nprintln(t\"t-string nested results: $success, $failure\")\n// Output: t-string nested results: Success(Success(42)), Success(Fail(failure!))\n```\n\n### TypeMap: Type-Safe Heterogeneous Maps\n\n`TypeMap` provides a type-safe heterogeneous map implementation, allowing you to store and retrieve values of different types using their types as keys. This is particularly useful for managing multiple types of data in a single structure with type safety.\n\n```scala\nimport kyo.*\n\n// Create an empty TypeMap\nval empty: TypeMap[Any] = TypeMap.empty\n\n// Constructors for up to 4 elements\nval map1: TypeMap[String] = TypeMap(\"Hello\")\nval map2: TypeMap[String \u0026 Int] = TypeMap(\"Hello\", 42)\nval map3: TypeMap[String \u0026 Int \u0026 Boolean] = TypeMap(\"Hello\", 42, true)\nval map4: TypeMap[String \u0026 Int \u0026 Boolean \u0026 Double] = TypeMap(\"Hello\", 42, true, 3.14)\n\n// Add a value to an existing TypeMap\nval mapWithNewValue: TypeMap[String \u0026 Int] = map1.add(42)\n\n// Retrieve a value from the TypeMap\nval str: String = map2.get[String]\nval num: Int = map2.get[Int]\n\n// Combine two TypeMaps\nval combined: TypeMap[String \u0026 Int \u0026 Boolean] = map2.union(TypeMap(true))\n\n// Filter the TypeMap to only include subtypes of a given type\nval pruned: TypeMap[String] = map2.prune[String]\n\n// Check if the TypeMap is empty and get its size\nval isEmpty: Boolean = map2.isEmpty\nval size: Int = map2.size\n\n// Get a string representation of the TypeMap\nval representation: String = map2.show\n```\n\nThe type parameter `A` in `TypeMap[A]` represents the intersection type of all stored values, ensuring type safety when retrieving values.\n\n### Ansi: Text Color and Formatting\n\nThe `Ansi` object provides utilities for adding ANSI color and formatting to strings, as well as a code highlighting feature. This can be useful for creating colorful console output or formatting text for better readability.\n\n```scala\nimport kyo.*\n\n// The 'String' extension methods require a separate import\nimport kyo.Ansi.*\n\n// Add colors to strings\nval redText: String = \"Error\".red\nval blueText: String = \"Info\".blue\n\n// Add text formatting\nval boldText: String = \"Important\".bold\nval underlinedText: String = \"Underlined\".underline\n\n// Combine colors and formatting\nval importantError: String = \"Critical Error\".red.bold\n\n// Strip ANSI codes from a string\nval plainText: String = \"\\u001b[31mColored\\u001b[0m\".stripAnsi\n\n// Highlight code snippets\nval code = \"\"\"\ndef hello(name: String): Unit =\nprintln(s\"Hello, $name!\")\n\"\"\"\nlazy val highlightedCode: String = Ansi.highlight(code)\n\n// Highlight code with custom header and trailer\nlazy val customHighlight: String = \n    Ansi.highlight(\n        header = \"// File: example.scala\",\n        code = code,\n        trailer = \"// End of file\",\n        startLine = 1\n    )\n```\n\nThe `Ansi` object provides the following color extensions for strings:\n- `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `grey`\n\nAnd the following formatting extensions:\n- `bold`, `dim`, `italic`, `underline`\n\nThe code highlighting feature supports basic syntax highlighting for Scala keywords, string literals, and comments.\n\n## Integrations\n\n### Cache: Memoized Functions via Caffeine\n\nKyo provides caching through memoization. A single `Cache` instance can be reused by multiple memoized functions. This allows for flexible scoping of caches, enabling users to use the same cache for various operations.\n\n```scala\nimport kyo.*\n\nval a: Int \u003c Async =\n    for\n\n        // The initialization takes a\n        // builder function that mirrors\n        // Caffeine's builder\n        cache \u003c- Cache.init(_.maxSize(100))\n\n        // Create a memoized function\n        fun = cache.memo { (v: String) =\u003e\n            // Note how the implementation\n            // can use other effects\n            Sync.defer(v.toInt)\n        }\n\n        // Use the function\n        v \u003c- fun(\"10\")\n    yield v\n```\n\nAlthough multiple memoized functions can reuse the same `Cache`, each function operates as an isolated cache and doesn't share any values with others. Internally, cache entries include the instance of the function as part of the key to ensure this separation. Only the cache space is shared, allowing for efficient use of resources without compromising the independence of each function's cache.\n\n### Requests: HTTP Client via Sttp\n\n`Requests` provides a simplified API for [Sttp 3](https://github.com/softwaremill/sttp) implemented on top of Kyo's concurrent package.\n\nTo perform a request, use the `apply` method. It takes a builder function based on Sttp's request building API.\n\n```scala\nimport kyo.*\nimport kyo.Requests.Backend\nimport sttp.client3.*\n\n// Perform a request using a builder function\nval a: String \u003c (Async \u0026 Abort[FailedRequest]) =\n    Requests(_.get(uri\"https://httpbin.org/get\"))\n\n// Alternatively, requests can be\n// defined separately\nval b: String \u003c (Async \u0026 Abort[FailedRequest]) =\n    Requests.request(Requests.basicRequest.get(uri\"https://httpbin.org/get\"))\n\n// It's possible to use the default implementation or provide\n// a custom `Backend` via `let`\n\n// An example request\nval c: String \u003c (Async \u0026 Abort[FailedRequest]) =\n    Requests(_.get(uri\"https://httpbin.org/get\"))\n\n// Implementing a custom mock backend\nval backend: Backend =\n    new Backend:\n        def send[T](r: Request[T, Any])(using Frame) =\n            Response.ok(Right(\"mocked\")).asInstanceOf[Response[T]]\n\n// Use the custom backend\nval d: String \u003c (Async \u0026 Abort[FailedRequest]) =\n    Requests.let(backend)(a)\n```\n\nPlease refer to Sttp's documentation for details on how to build requests. Streaming is currently unsupported.\n\nUsers are free to use any JSON libraries supported by Sttp; however, [zio-json](https://github.com/zio/zio-json) is recommended, as it is used in Kyo's tests and modules requiring HTTP communication, such as `AIs`.\n\n### Routes: HTTP Server via Tapir\n\n`Routes` integrates with the Tapir library to help set up HTTP servers. The method `Routes.add` is used for adding routes. This method requires the definition of a route, which can be a Tapir Endpoint instance or a builder function. Additionally, the method requires the implementation of the endpoint, which is provided as the second parameter group. To start the server, the `Routes` effect is handled, which initializes the HTTP server with the specified routes.\n\n```scala\nimport kyo.*\nimport sttp.tapir.*\nimport sttp.tapir.server.netty.*\n\n// A simple health route using an endpoint builder\nval a: Unit \u003c Routes =\n    Routes.add(\n        _.get.in(\"health\")\n            .out(stringBody)\n    ) { _ =\u003e\n        \"ok\"\n    }\n\n// The endpoint can also be defined separately\nval health2 = endpoint.get.in(\"health2\").out(stringBody)\n\nval b: Unit \u003c Routes =\n    Routes.add(health2)(_ =\u003e \"ok\")\n\n// Starting the server by handling the effect\nval c: NettyKyoServerBinding \u003c Async =\n    Routes.run(a.andThen(b))\n\n// Alternatively, a customized server configuration can be used\nval d: NettyKyoServerBinding \u003c Async =\n    Routes.run(NettyKyoServer().port(9999))(a.andThen(b))\n```\n\nThe parameters for Tapir's endpoint type are aligned with Kyo effects as follows:\n\n`Endpoint[SECURITY_INPUT, INPUT, ERROR_OUTPUT, OUTPUT, CAPABILITIES]`\n\nThis translates to the endpoint function format:\n\n`INPUT =\u003e OUTPUT \u003c (Env[SECURITY_INPUT] \u0026 Abort[ERROR_OUTPUT])`\n\nCurrently, the `CAPABILITIES` parameter is not supported in Kyo since streaming functionality is not available. An example of using these parameters is shown below:\n\n```scala\nimport kyo.*\nimport sttp.model.*\nimport sttp.tapir.*\n\n// An endpoint with an 'Int' path input and 'StatusCode' error output\nval a: Unit \u003c Routes =\n    Routes.add(\n        _.get.in(\"test\" / path[Int](\"id\"))\n            .errorOut(statusCode)\n            .out(stringBody)\n    ) { (id: Int) =\u003e\n        if id == 42 then \"ok\"\n        else Abort.fail(StatusCode.NotFound)\n        // returns a 'String \u003c Abort[StatusCode]'\n    }\n```\n\nFor further examples, refer to TechEmpower's benchmark [subproject](https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Scala/kyo-tapir) for a simple runnable demonstration, and  Kyo's [example ledger service](https://github.com/getkyo/kyo/tree/main/kyo-examples/jvm/src/main/scala/examples/ledger) for practical applications of these concepts.\n\n### ZIOs: Integration with ZIO\n\nThe `ZIOs` effect provides seamless integration between Kyo and the ZIO library. The effect is designed to enable gradual adoption of Kyo within a ZIO codebase. The integration properly suspends side effects and propagates fiber cancellations/interrupts between both libraries.\n\n```scala\nimport kyo.*\nimport zio.*\n\n// Use the 'get' method to extract a 'ZIO' effect\nval a: Int \u003c (Abort[Nothing] \u0026 Async) =\n    ZIOs.get(ZIO.succeed(42))\n\n// 'get' also supports error handling with 'Abort'\nval b: Int \u003c (Abort[String] \u0026 Async) =\n    ZIOs.get(ZIO.fail(\"error\"))\n\n// Handle the 'ZIO' effect to obtain a 'ZIO' effect\nval c: Task[Int] =\n    ZIOs.run(a)\n```\n\nKyo and ZIOs effects can be seamlessly mixed and matched within computations, allowing developers to leverage the power of both libraries. Here are a few examples showcasing this integration:\n\n```scala\nimport kyo.*\nimport zio.{Fiber =\u003e _, *}\n\n// Note how ZIO includes the\n// Sync and Async effects\nval a: Int \u003c (Abort[Nothing] \u0026 Async) =\n    for\n        v1 \u003c- ZIOs.get(ZIO.succeed(21))\n        v2 \u003c- Sync.defer(21)\n        v3 \u003c- Fiber.initUnscoped(-42).map(_.get)\n    yield v1 + v2 + v3\n\n// Using fibers from both libraries\nval b: Int \u003c (Abort[Nothing] \u0026 Async) =\n    for\n        f1 \u003c- ZIOs.get(ZIO.succeed(21).fork)\n        f2 \u003c- Fiber.initUnscoped(Sync.defer(21))\n        v1 \u003c- ZIOs.get(f1.join)\n        v2 \u003c- f2.get\n    yield v1 + v2\n\n// Transforming ZIO effects within Kyo computations\nval c: Int \u003c (Abort[Nothing] \u0026 Async) =\n    ZIOs.get(ZIO.succeed(21)).map(_ * 2)\n\n// Transforming Kyo effects within ZIO effects\nval d: Task[Int] =\n    ZIOs.run(Sync.defer(21).map(_ * 2))\n```\n\n\u003e Note: Support for ZIO environments (`R` in `ZIO[R, E, A]`) is currently in development. Once implemented, it will be possible to use ZIO effects with environments directly within Kyo computations.\n\n### Cats: Integration with Cats Effect\n\nThe `Cats` effect provides seamless integration between Kyo and the Cats Effect library. This integration is designed to enable gradual adoption of Kyo within a Cats Effect codebase. The integration properly suspends side effects and propagates fiber cancellations/interrupts between both libraries.\n\n```scala\nimport kyo.*\nimport cats.effect.IO as CatsIO\n\n// Use the 'get' method to extract a 'Sync' effect from Cats Effect:\nval a: Int \u003c (Abort[Throwable] \u0026 Async) =\n    Cats.get(CatsIO.pure(42))\n\n// Handle the 'Cats' effect to obtain a 'CatsIO' effect:\nval b: CatsIO[Int] =\n    Cats.run(a)\n```\n\nKyo and Cats effects can be seamlessly mixed and matched within computations, allowing developers to leverage the power of both libraries. Here are a few examples showcasing this integration:\n\n```scala\nimport kyo.*\nimport cats.effect.IO as CatsIO\nimport cats.effect.kernel.Outcome.Succeeded\n\n// Note how Cats includes the Sync, Async, and Abort[Nothing] effects:\nval a: Int \u003c (Abort[Nothing] \u0026 Async) =\n    for\n        v1 \u003c- Cats.get(CatsIO.pure(21))\n        v2 \u003c- Sync.defer(21)\n        v3 \u003c- Fiber.initUnscoped(-42).map(_.get)\n    yield v1 + v2 + v3\n\n// Using fibers from both libraries:\nval b: Int \u003c (Abort[Nothing] \u0026 Async) =\n    for\n        f1 \u003c- Cats.get(CatsIO.pure(21).start)\n        f2 \u003c- Fiber.initUnscoped(Sync.defer(21))\n        v1 \u003c- Cats.get(f1.joinWith(CatsIO(99)))\n        v2 \u003c- f2.get\n    yield v1 + v2\n\n// Transforming Cats Effect Sync within Kyo computations:\nval c: Int \u003c (Abort[Nothing] \u0026 Async) =\n    Cats.get(CatsIO.pure(21)).map(_ * 2)\n\n// Transforming Kyo effects within Cats Effect Sync:\nval d: CatsIO[Int] =\n    Cats.run(Sync.defer(21).map(_ * 2))\n```\n\n### Resolvers: GraphQL Server via Caliban\n\n`Resolvers` integrates with the [Caliban](https://github.com/ghostdogpr/caliban) library to help setup GraphQL servers.\n\nThe first integration is that you can use Kyo effects inside your Caliban schemas by importing `kyo.given`.\n- If your Kyo effects is `(Abort[Throwable] \u0026 ZIO)` or a subtype of it (`ZIO` includes `Async \u0026 Sync`), a Caliban `Schema` can be derived automatically.\n- If your Kyo effect is something else, a Caliban schema can be derived if it has a `Runner` for that effect as part of ZIO environment.\n\n```scala\nimport caliban.schema.*\nimport kyo.*\nimport kyo.given\n\n// this works by just importing kyo.*\ncase class Query(k: Int \u003c Abort[Throwable]) derives Schema.SemiAuto\n\n// for other effects, you need to extend `SchemaDerivation[Runner[YourCustomEffects]]`\ntype CustomEffects = Var[Int] \u0026 Env[String]\nobject schema extends SchemaDerivation[Runner[CustomEffects]]\n\ncase class Query2(k: Int \u003c CustomEffects) derives schema.SemiAuto\n```\n\nThen, the `Resolvers` effect allows easily turning these schemas into a GraphQL server.\nThe method `Resolvers.get` is used for importing a `GraphQL` object from Caliban into Kyo.\nYou can then run this effect using `Resolvers.run` to get an HTTP server. This effect requires `ZIO` because Caliban uses ZIO internally to run.\n\n```scala\nimport caliban.*\nimport caliban.schema.*\nimport kyo.*\nimport kyo.given\nimport sttp.tapir.server.netty.*\nimport zio.Task\n\ncase class Query(k: Int \u003c Abort[Throwable]) derives Schema.SemiAuto\nval api = graphQL(RootResolver(Query(42)))\n\nval a: NettyKyoServerBinding \u003c (Async \u0026 Abort[CalibanError]) =\n    Resolvers.run { Resolvers.get(api) }\n\n// similarly to the tapir integration, you can also pass a `NettyKyoServer` explicitly\nval b: NettyKyoServerBinding \u003c (Async \u0026 Abort[CalibanError]) =\n    Resolvers.run(NettyKyoServer().port(9999)) { Resolvers.get(api) }\n\n// you can turn this into a ZIO as seen in the ZIO integration\nval c: Task[NettyKyoServerBinding] = ZIOs.run(b)\n```\n\nWhen using arbitrary Kyo effects, you need to provide the `Runner` for that effect when calling the `run` function.\n```scala\nimport caliban.*\nimport caliban.schema.*\nimport kyo.*\nimport kyo.given\nimport zio.Task\n\ntype CustomEffects = Var[Int] \u0026 Env[String]\nobject schema extends SchemaDerivation[Runner[CustomEffects]]\ncase class Query(k: Int \u003c CustomEffects) derives schema.SemiAuto\n\nval api = graphQL(RootResolver(Query(42)))\n\n// runner for our CustomEffects\nval runner = new Runner[CustomEffects]:\n    def apply[T](v: T \u003c CustomEffects): Task[T] = ZIOs.run(Env.run(\"kyo\")(Var.run(0)(v)))\n\nval d = Resolvers.run(runner) { Resolvers.get(api) }\n```\n\n### AIs: LLM Abstractions via OpenAI\n\nComing soon..\n\n## ZIO-like Combinators\n\nFor ZIO users, Kyo's core API can be frustrating for three reasons:\n\n1. It is minimal by design.\n\nWhile its uncluttered namespaces make it more approachable for beginners, users addicted to ZIO's powerful and intuitive combinators may find it unwieldy and possibly not worth the effort.\n\n2. Effects are handled by functions that take effects as arguments, rather than by methods on effects.\n\nZIO users are used to having a large menu of combinators on `ZIO` values that can be chained together to manipulate effects fluently. `kyo-core`, by contrast, requires nesting effects within method calls, inverting the order in which users handle effects and requiring them either to create deeply nested expressions or to break expressions up into many intermediate expressions.\n\n3. Factory methods are distributed among different objects\n\nBeing more modular than ZIO, Kyo separates effect constructors in the companion objects to their corresponding types. This is not a problem given the minimal API that Kyo offers, but ZIO users will miss typing `ZIO.` and seeing a rich menu of factory methods pop up on their IDE.\n\n`kyo-combinators` alleviates these frustrations by providing:\n1. Factory methods on the `Kyo` object, styled after those found on `ZIO`, for many of the core Kyo effect types.\n2. Extension methods on Kyo effects modeled similarly to ZIO's methods.\n\n### Simple example\n\n```scala mdoc:skip\nimport kyo.*\nimport scala.concurrent.duration.*\nimport java.io.IOException\n\ntrait HelloService:\n    def sayHelloTo(saluee: String): Unit \u003c (Sync \u0026 Abort[Throwable])\n\nobject HelloService:\n    val live = Layer(Live)\n\n    object Live extends HelloService:\n        override def sayHelloTo(saluee: String): Unit \u003c (Sync \u0026 Abort[Throwable]) =\n            Kyo.deferAttempt { // Introduces Sync \u0026 Abort[Throwable] effect\n                println(s\"Hello $saluee!\")\n            }\n    end Live\nend HelloService\n\nval keepTicking: Nothing \u003c (Async \u0026 Emit[String]) =\n    (Kyo.emit(\".\") *\u003e Kyo.sleep(1.second)).forever\n\nval effect: Unit \u003c (Async \u0026 Scope \u0026 Abort[Throwable] \u0026 Env[HelloService]) =\n    for\n        nameService \u003c- Kyo.service[HelloService]      // Introduces Env[NameService]\n        _           \u003c- keepTicking                    // Introduces Async and Emit[String]\n            .foreachEmit(Console.print)               // Handles Emit[String] and introduces Abort[IOException]\n            .forkScoped                               // Introduces Scope\n        saluee      \u003c- Console.readln\n        _           \u003c- Kyo.sleep(2.seconds)\n        _           \u003c- nameService.sayHelloTo(saluee) // Lifts Abort[IOException] to Abort[Throwable]\n    yield ()\n    end for\nend effect\n\n// There are no combinators for handling Sync or blocking Async, since this should\n// be done at the edge of the program\nSync.Unsafe.run {                        // Handles Sync\n    KyoApp.runAndBlock(Duration.Inf) {  // Handles Async\n        Kyo.scoped {                   // Handles Scope\n            Memo.run:                  // Handles Memo (introduced by .provide, below)\n                effect\n                    .catching((thr: Throwable) =\u003e             // Handles Abort[Throwable]\n                        Kyo.debug(s\"Failed printing to console: ${throwable}\")\n                    )\n                    .provide(HelloService.live)                 // Works like ZIO[R,E,A]#provide, but introduces Memo effect\n        }\n    }\n}\n```\n\n### Error handling\n\nWhereas ZIO has a single channel for describing errors, Kyo has different effect types that can describe failure in the basic sense of \"short-circuiting\": `Abort` and `Choice` (an empty `Seq` being equivalent to a short-circuit). `Abort[Absent]` can also be used like `Choice` to model short-circuiting an empty result.\n\nFor each of these, to handle the effect, lifting the result type to `Result`, `Seq`, and `Maybe`, use `.result`, `.handleChoice`, and `.maybe` respectively. Alternatively, you can convert between these different error types using methods usually in the form of `def effect1ToEffect2`, where `effect1` and `effect2` can be \"abort\" (`Abort[?]`), \"absent\" (`Abort[Absent]`), \"empty\" (`Choice`, when reduced to an empty sequence), and \"throwable\" (`Abort[Throwable]`).\n\nSome examples:\n\n```scala \nval abortEffect: Int \u003c Abort[String] = 1\n\n// Converts failures to empty failure\nval maybeEffect: Int \u003c Abort[Absent] = abortEffect.abortToAbsent\n\n// Converts an aborted Absent to a dropped (i.e., empty) \"choice\"\nval choiceEffect: Int \u003c Choice = maybeEffect.absentToChoiceDrop\n\n// Fails with exception if choice is dropped\nval newAbortEffect: Int \u003c (Choice \u0026 Abort[Throwable]) = choiceEffect.choiceDropToThrowable\n```\n\nTo swallow errors à la ZIO's `orDie` and `resurrect` methods, you can use `orPanic`/`orThrow` and `unpanic` respectively:\n\n```scala\nimport kyo.*\nimport java.io.IOException\n\nval abortEffect: Int \u003c Abort[String | Throwable] = 1\n\n// Will panic with a `PanicException(err)` rather than fail\nval panicEffect: Int \u003c Abort[Nothing] = abortEffect.orPanic\n\n// Will throw `PanicException(err)` when evaluated\nval unsafeEffect: Int \u003c Any = abortEffect.orThrow\n\n// Catch any suspended throws\nval safeEffect: Int \u003c Abort[Throwable] = unsafeEffect.unpanic\n\n// Use orPanic after forAbort[E] to swallow only errors of type E\nval unsafeForThrowables: Int \u003c Abort[String] = abortEffect.forAbort[Throwable].orPanic\n```\n\nIn general `orPanic` should be preferred over `orThrow`, especially when used in conjunction with `Sync` or `Async`, both of which include `Abort[Nothing]`. This will avoid unnecessary catching/re-throwing.\n\nOther error-handling methods are as follows:\n\n```scala\nimport kyo.*\n\ntrait A\ntrait B\ntrait C\n\nval effect: Int \u003c Abort[A | B | C] = 1\n\nval handled: Result[A | B | C, Int] \u003c Any = effect.result\nval handledWithoutPanic: Result.Partial[A | B | C, Int] \u003c Abort[Nothing] = effect.resultPartial\nval unsafeHandled: Result.Partial[A | B | C, Int] \u003c Any = effect.resultPartialOrThrow\nval folded: String \u003c Any = effect.foldAbort(_.toString, _.toString, _.toString)\nval foldedWithoutPanic: String \u003c Abort[Nothing] = effect.foldAbort(_.toString, _.toString)\nval unsafeFolded: String \u003c Any = effect.foldAbortOrThrow(_.toString, _.toString)\nval mappedError: Int \u003c Abort[String] = effect.mapAbort(_.toString)\nval recovered: Int \u003c Abort[Nothing] = effect.recover(_.toString.size)\nval partiallyRecovered: Int \u003c Abort[A | B | C] = effect.recoverSome { case err if err.toString.size \u003e 5 =\u003e 0 }\nval swapped: (A | B | C) \u003c Abort[Int] = effect.swapAbort\nval retried: Int \u003c Abort[A | B | C] = effect.retry(5)\nval retriedUntilSucceed: Int \u003c Any = effect.retryForever\n\n// Select error types within the Abort union for handling\nval handledA: Result[A, Int] \u003c Abort[B | C] = effect.forAbort[A].result\nval handledWithoutPanicA: Result.Partial[A, Int] \u003c Abort[B | C] = effect.forAbort[A].resultPartial\nval foldedA: String \u003c Abort[B | C] = effect.forAbort[A].fold(_.toString, _.toString, _.toString)\nval foldedWithoutPanicA: String \u003c Abort[B | C] = effect.forAbort[A].fold(_.toString, _.toString)\nval recoveredA: Int \u003c Abort[B | C] = effect.forAbort[A].recover(_.toString.size)\nval partiallyRecoveredA: Int \u003c Abort[A | B | C] = effect.forAbort[A].recoverSome { case err if err.toString.size \u003e 5 =\u003e 0 }\nval aSwapped: A \u003c Abort[Int | B | C] = effect.forAbort[A].swap\nval aToAbsent: Int \u003c Abort[Absent | B | C] = effect.forAbort[A].toAbsent\nval aToEmpty: Int \u003c (Choice \u0026 Abort[B | C]) = effect.forAbort[A].toChoiceDrop\nval aToThrowable: Int \u003c Abort[Throwable | B | C] = effect.forAbort[A].toThrowable\nval retriedA: Int \u003c (Abort[A | B | C]) = effect.forAbort[A].retry(5)\nval retriedAUntilSucceed: Int \u003c (Abort[B | C]) = effect.forAbort[A].retryForever\n```\n\n\n## Acknowledgements\n\nKyo's development was originally inspired by the paper [\"Do Be Do Be Do\"](https://arxiv.org/pdf/1611.09259.pdf) and its implementation in the [Unison](https://www.unison-lang.org/learn/language-reference/abilities-and-ability-handlers/) programming language. Kyo's design evolved from using interface-based effects to suspending concrete values associated with specific effects, making it more efficient when executed on the JVM.\n\nAdditionally, Kyo draws inspiration from [ZIO](https://zio.dev/) in various aspects. The core mechanism for algebraic effects can be seen as a generalization of ZIO's [effect rotation](https://degoes.net/articles/rotating-effects), and many of Kyo's effects are directly influenced by ZIO's mature set of primitives. For instance, `Env` and `Abort` correspond to ZIO's effect channels, `Scope` functions similarly to `Scope`, and `Hub` was introduced based on ZIO. This design keeps a focus on easy composition when using Kyo and ZIO in the same program, and lowers the barrier for developers familiar with ZIO to adopt Kyo.\n\nKyo's asynchronous primitives take several aspects from [Twitter's util](https://github.com/twitter/util) and [Finagle](https://github.com/twitter/finagle), including features like async root compression, to provide stack safety, and support for cancellations (interruptions in Kyo).\n\nLastly, the name \"Kyo\" is derived from the last character of Nam-myoho-renge-kyo, the mantra practiced in [SGI Buddhism](https://www.sokaglobal.org/). It literally translates to \"Sutra,\" referring to a compiled teaching of Shakyamuni Buddha, and is also interpreted as the \"threads\" that weave the fundamental fabric of life's reality.\n\nLicense\n-------\n\nSee the [LICENSE](https://github.com/getkyo/kyo/blob/master/LICENSE.txt) file for details.\n","funding_links":[],"categories":["\u003ca name=\"Scala\"\u003e\u003c/a\u003eScala"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetkyo%2Fkyo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgetkyo%2Fkyo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetkyo%2Fkyo/lists"}