effect 3.11.8 → 3.11.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/cjs/Effect.js +1685 -293
  2. package/dist/cjs/Effect.js.map +1 -1
  3. package/dist/cjs/Option.js +1 -1
  4. package/dist/cjs/Schema.js +57 -40
  5. package/dist/cjs/Schema.js.map +1 -1
  6. package/dist/cjs/SchemaAST.js +44 -42
  7. package/dist/cjs/SchemaAST.js.map +1 -1
  8. package/dist/cjs/internal/core-effect.js +3 -3
  9. package/dist/cjs/internal/core-effect.js.map +1 -1
  10. package/dist/cjs/internal/fiberRuntime.js +4 -4
  11. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  12. package/dist/cjs/internal/version.js +1 -1
  13. package/dist/dts/Effect.d.ts +12053 -8146
  14. package/dist/dts/Effect.d.ts.map +1 -1
  15. package/dist/dts/Option.d.ts +1 -1
  16. package/dist/dts/Schema.d.ts +1 -1
  17. package/dist/dts/Schema.d.ts.map +1 -1
  18. package/dist/dts/SchemaAST.d.ts +9 -1
  19. package/dist/dts/SchemaAST.d.ts.map +1 -1
  20. package/dist/dts/internal/core-effect.d.ts.map +1 -1
  21. package/dist/esm/Effect.js +1734 -294
  22. package/dist/esm/Effect.js.map +1 -1
  23. package/dist/esm/Option.js +1 -1
  24. package/dist/esm/Schema.js +57 -40
  25. package/dist/esm/Schema.js.map +1 -1
  26. package/dist/esm/SchemaAST.js +43 -41
  27. package/dist/esm/SchemaAST.js.map +1 -1
  28. package/dist/esm/internal/core-effect.js +3 -3
  29. package/dist/esm/internal/core-effect.js.map +1 -1
  30. package/dist/esm/internal/fiberRuntime.js +4 -4
  31. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  32. package/dist/esm/internal/version.js +1 -1
  33. package/package.json +1 -1
  34. package/src/Effect.ts +7191 -3280
  35. package/src/Option.ts +1 -1
  36. package/src/Schema.ts +57 -42
  37. package/src/SchemaAST.ts +52 -44
  38. package/src/internal/core-effect.ts +11 -8
  39. package/src/internal/fiberRuntime.ts +14 -14
  40. package/src/internal/version.ts +1 -1
@@ -20,22 +20,50 @@ import { internalCall, isGeneratorFunction } from "./Utils.js";
20
20
  */
21
21
  export const EffectTypeId = core.EffectTypeId;
22
22
  /**
23
- * This function returns `true` if the specified value is an `Effect` value,
24
- * `false` otherwise.
23
+ * Checks if a given value is an `Effect` value.
24
+ *
25
+ * **When to Use**
25
26
  *
26
27
  * This function can be useful for checking the type of a value before
27
28
  * attempting to operate on it as an `Effect` value. For example, you could use
28
- * `isEffect` to check the type of a value before using it as an argument to a
29
- * function that expects an `Effect` value.
29
+ * `Effect.isEffect` to check the type of a value before using it as an argument
30
+ * to a function that expects an `Effect` value.
30
31
  *
31
32
  * @since 2.0.0
32
- * @category Condition Checking
33
+ * @category Guards
33
34
  */
34
35
  export const isEffect = core.isEffect;
35
36
  /**
36
- * Returns an effect that caches its result for a specified duration, known as
37
- * the `timeToLive`. When the cache expires after the duration, the effect will
38
- * be recomputed upon next evaluation.
37
+ * Returns an effect that caches its result for a specified `Duration`,
38
+ * known as "timeToLive" (TTL).
39
+ *
40
+ * **Details**
41
+ *
42
+ * This function is used to cache the result of an effect for a specified amount
43
+ * of time. This means that the first time the effect is evaluated, its result
44
+ * is computed and stored.
45
+ *
46
+ * If the effect is evaluated again within the specified `timeToLive`, the
47
+ * cached result will be used, avoiding recomputation.
48
+ *
49
+ * After the specified duration has passed, the cache expires, and the effect
50
+ * will be recomputed upon the next evaluation.
51
+ *
52
+ * **When to Use**
53
+ *
54
+ * Use this function when you have an effect that involves costly operations or
55
+ * computations, and you want to avoid repeating them within a short time frame.
56
+ *
57
+ * It's ideal for scenarios where the result of an effect doesn't change
58
+ * frequently and can be reused for a specified duration.
59
+ *
60
+ * By caching the result, you can improve efficiency and reduce unnecessary
61
+ * computations, especially in performance-critical applications.
62
+ *
63
+ * @see {@link cached} for a similar function that caches the result
64
+ * indefinitely.
65
+ * @see {@link cachedInvalidateWithTTL} for a similar function that includes an
66
+ * additional effect for manually invalidating the cached value.
39
67
  *
40
68
  * @example
41
69
  * ```ts
@@ -73,9 +101,36 @@ export const isEffect = core.isEffect;
73
101
  */
74
102
  export const cachedWithTTL = circular.cached;
75
103
  /**
76
- * Similar to {@link cachedWithTTL}, this function caches an effect's result for
77
- * a specified duration. It also includes an additional effect for manually
78
- * invalidating the cached value before it naturally expires.
104
+ * Caches an effect's result for a specified duration and allows manual
105
+ * invalidation before expiration.
106
+ *
107
+ * **Details**
108
+ *
109
+ * This function behaves similarly to {@link cachedWithTTL} by caching the
110
+ * result of an effect for a specified period of time. However, it introduces an
111
+ * additional feature: it provides an effect that allows you to manually
112
+ * invalidate the cached result before it naturally expires.
113
+ *
114
+ * This gives you more control over the cache, allowing you to refresh the
115
+ * result when needed, even if the original cache has not yet expired.
116
+ *
117
+ * Once the cache is invalidated, the next time the effect is evaluated, the
118
+ * result will be recomputed, and the cache will be refreshed.
119
+ *
120
+ * **When to Use**
121
+ *
122
+ * Use this function when you have an effect whose result needs to be cached for
123
+ * a certain period, but you also want the option to refresh the cache manually
124
+ * before the expiration time.
125
+ *
126
+ * This is useful when you need to ensure that the cached data remains valid for
127
+ * a certain period but still want to invalidate it if the underlying data
128
+ * changes or if you want to force a recomputation.
129
+ *
130
+ * @see {@link cached} for a similar function that caches the result
131
+ * indefinitely.
132
+ * @see {@link cachedWithTTL} for a similar function that caches the result for
133
+ * a specified duration but does not include an effect for manual invalidation.
79
134
  *
80
135
  * @example
81
136
  * ```ts
@@ -116,9 +171,27 @@ export const cachedWithTTL = circular.cached;
116
171
  */
117
172
  export const cachedInvalidateWithTTL = circular.cachedInvalidateWithTTL;
118
173
  /**
119
- * Returns an effect that computes a result lazily and caches it. Subsequent
120
- * evaluations of this effect will return the cached result without re-executing
121
- * the logic.
174
+ * Returns an effect that lazily computes a result and caches it for subsequent
175
+ * evaluations.
176
+ *
177
+ * **Details**
178
+ *
179
+ * This function wraps an effect and ensures that its result is computed only
180
+ * once. Once the result is computed, it is cached, meaning that subsequent
181
+ * evaluations of the same effect will return the cached result without
182
+ * re-executing the logic.
183
+ *
184
+ * **When to Use**
185
+ *
186
+ * Use this function when you have an expensive or time-consuming operation that
187
+ * you want to avoid repeating. The first evaluation will compute the result,
188
+ * and all following evaluations will immediately return the cached value,
189
+ * improving performance and reducing unnecessary work.
190
+ *
191
+ * @see {@link cachedWithTTL} for a similar function that includes a
192
+ * time-to-live duration for the cached value.
193
+ * @see {@link cachedInvalidateWithTTL} for a similar function that includes an
194
+ * additional effect for manually invalidating the cached value.
122
195
  *
123
196
  * @example
124
197
  * ```ts
@@ -162,9 +235,30 @@ export const cachedInvalidateWithTTL = circular.cachedInvalidateWithTTL;
162
235
  */
163
236
  export const cached = effect.memoize;
164
237
  /**
165
- * Returns a memoized version of a function with effects. Memoization ensures
166
- * that results are stored and reused for the same inputs, reducing the need to
167
- * recompute them.
238
+ * Returns a memoized version of a function with effects, reusing results for
239
+ * the same inputs.
240
+ *
241
+ * **Details**
242
+ *
243
+ * This function creates a memoized version of a given function that performs an
244
+ * effect. Memoization ensures that once a result is computed for a specific
245
+ * input, it is stored and reused for subsequent calls with the same input,
246
+ * reducing the need to recompute the result.
247
+ *
248
+ * The function can optionally take an `Equivalence` parameter to
249
+ * determine how inputs are compared for caching purposes.
250
+ *
251
+ * **When to Use**
252
+ *
253
+ * Use this function when you have a function that performs an effect and you
254
+ * want to avoid recomputing the result for the same input multiple times.
255
+ *
256
+ * It's ideal for functions that produce deterministic results based on their
257
+ * inputs, and you want to improve performance by caching the output.
258
+ *
259
+ * This is particularly useful in scenarios where the function involves
260
+ * expensive calculations or operations that should be avoided after the first
261
+ * execution with the same parameters.
168
262
  *
169
263
  * @example
170
264
  * ```ts
@@ -200,6 +294,20 @@ export const cachedFunction = circular.cachedFunction;
200
294
  * Returns an effect that executes only once, regardless of how many times it's
201
295
  * called.
202
296
  *
297
+ * **Details**
298
+ *
299
+ * This function ensures that a specific effect is executed only a single time,
300
+ * no matter how many times it is invoked. The result of the effect will be
301
+ * cached, and subsequent calls to the effect will immediately return the cached
302
+ * result without re-executing the original logic.
303
+ *
304
+ * **When to Use**
305
+ *
306
+ * Use this function when you need to perform a task only once, regardless of
307
+ * how many times the effect is triggered. It's particularly useful when you
308
+ * have initialization tasks, logging, or other one-time actions that should not
309
+ * be repeated. This can help optimize performance and avoid redundant actions.
310
+ *
203
311
  * @example
204
312
  * ```ts
205
313
  * import { Effect, Console } from "effect"
@@ -227,9 +335,9 @@ export const once = effect.once;
227
335
  * Combines multiple effects into one, returning results based on the input
228
336
  * structure.
229
337
  *
230
- * **When to Use**
338
+ * **Details**
231
339
  *
232
- * Use `Effect.all` when you need to run multiple effects and combine their
340
+ * Use this function when you need to run multiple effects and combine their
233
341
  * results into a single output. It supports tuples, iterables, structs, and
234
342
  * records, making it flexible for different input types.
235
343
  *
@@ -252,8 +360,8 @@ export const once = effect.once;
252
360
  *
253
361
  * **Short-Circuiting Behavior**
254
362
  *
255
- * The `Effect.all` function stops execution on the first error it encounters,
256
- * this is called "short-circuiting". If any effect in the collection fails, the
363
+ * This function stops execution on the first error it encounters, this is
364
+ * called "short-circuiting". If any effect in the collection fails, the
257
365
  * remaining effects will not run, and the error will be propagated. To change
258
366
  * this behavior, you can use the `mode` option, which allows all effects to run
259
367
  * and collect results as `Either` or `Option`.
@@ -271,6 +379,7 @@ export const once = effect.once;
271
379
  * the error for failure.
272
380
  *
273
381
  * @see {@link forEach} for iterating over elements and applying an effect.
382
+ * @see {@link allWith} for a data-last version of this function.
274
383
  *
275
384
  * @example
276
385
  * ```ts
@@ -435,9 +544,9 @@ export const all = fiberRuntime.all;
435
544
  *
436
545
  * **When to Use**
437
546
  *
438
- * The `allWith` function enables you to combine multiple effects and customize execution options
439
- * such as concurrency levels. This version is useful in functional pipelines where you first define
440
- * your data and then apply operations to it.
547
+ * This function enables you to combine multiple effects and customize execution
548
+ * options such as concurrency levels. This version is useful in functional
549
+ * pipelines where you first define your data and then apply operations to it.
441
550
  *
442
551
  * @example
443
552
  * ```ts
@@ -471,45 +580,353 @@ export const all = fiberRuntime.all;
471
580
  */
472
581
  export const allWith = fiberRuntime.allWith;
473
582
  /**
474
- * Evaluate and run each effect in the structure and collect the results,
475
- * discarding results from failed effects.
583
+ * Evaluates and runs each effect in the iterable, collecting only the
584
+ * successful results while discarding failures.
585
+ *
586
+ * **Details**
587
+ *
588
+ * This function function processes an iterable of effects and runs each one. If
589
+ * an effect is successful, its result is collected; if it fails, the result is
590
+ * discarded. This ensures that only successful outcomes are kept.
591
+ *
592
+ * **Options**
593
+ *
594
+ * The function also allows you to customize how the effects are handled by
595
+ * specifying options such as concurrency, batching, and how finalizers behave.
596
+ * These options provide flexibility in running the effects concurrently or
597
+ * adjusting other execution details.
598
+ *
599
+ * @example
600
+ * ```ts
601
+ * import { Effect } from "effect"
602
+ *
603
+ * const tasks = [
604
+ * Effect.succeed(1),
605
+ * Effect.fail("Error 1"),
606
+ * Effect.succeed(2),
607
+ * Effect.fail("Error 2")
608
+ * ]
609
+ *
610
+ * const program = Effect.gen(function*() {
611
+ * const successfulResults = yield* Effect.allSuccesses(tasks)
612
+ * console.log(successfulResults)
613
+ * })
614
+ *
615
+ * Effect.runFork(program)
616
+ * // Output: [1, 2]
617
+ *
618
+ * ```
476
619
  *
477
620
  * @since 2.0.0
478
621
  * @category Collecting
479
622
  */
480
623
  export const allSuccesses = fiberRuntime.allSuccesses;
481
624
  /**
482
- * Drops all elements until the effectful predicate returns true.
625
+ * Drops elements until the effectful predicate returns `true`.
626
+ *
627
+ * **Details**
628
+ *
629
+ * This function processes a collection of elements and uses an effectful
630
+ * predicate to determine when to stop dropping elements. It drops elements from
631
+ * the beginning of the collection until the predicate returns `true`.
632
+ *
633
+ * The predicate is a function that takes an element and its index in the
634
+ * collection and returns an effect that evaluates to a boolean.
635
+ *
636
+ * Once the predicate returns `true`, the remaining elements of the collection
637
+ * are returned.
638
+ *
639
+ * **Note**: The first element for which the predicate returns `true` is also
640
+ * dropped.
641
+ *
642
+ * **When to Use**
643
+ *
644
+ * This function allows you to conditionally skip over a part of the collection
645
+ * based on some criteria defined in the predicate.
646
+ *
647
+ * @see {@link dropWhile} for a similar function that drops elements while the
648
+ * predicate returns `true`.
649
+ *
650
+ * @example
651
+ * ```ts
652
+ * import { Effect } from "effect"
653
+ *
654
+ * const numbers = [1, 2, 3, 4, 5, 6]
655
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 3)
656
+ *
657
+ * const program = Effect.gen(function*() {
658
+ * const result = yield* Effect.dropUntil(numbers, predicate)
659
+ * console.log(result)
660
+ * })
661
+ *
662
+ * Effect.runFork(program)
663
+ * // Output: [5, 6]
664
+ * ```
483
665
  *
484
666
  * @since 2.0.0
485
667
  * @category Collecting
486
668
  */
487
669
  export const dropUntil = effect.dropUntil;
488
670
  /**
489
- * Drops all elements so long as the predicate returns true.
671
+ * Drops elements as long as the predicate returns `true`.
672
+ *
673
+ * **Details**
674
+ *
675
+ * This function processes a collection of elements and uses a predicate to
676
+ * decide whether to drop an element.
677
+ *
678
+ * The predicate is a function that takes an element and its index, and it
679
+ * returns an effect that evaluates to a boolean.
680
+ *
681
+ * As long as the predicate returns `true`, elements will continue to be dropped
682
+ * from the collection.
683
+ *
684
+ * Once the predicate returns `false`, the remaining elements are kept.
685
+ *
686
+ * **When to Use**
687
+ *
688
+ * This function allows you to discard elements from the start of a collection
689
+ * based on a condition, and only keep the rest when the condition no longer
690
+ * holds.
691
+ *
692
+ * @see {@link dropUntil} for a similar function that drops elements until the
693
+ * predicate returns `true`.
694
+ *
695
+ * @example
696
+ * ```ts
697
+ * import { Effect } from "effect"
698
+ *
699
+ * const numbers = [1, 2, 3, 4, 5, 6]
700
+ * const predicate = (n: number, i: number) => Effect.succeed(n <= 3)
701
+ *
702
+ * const program = Effect.gen(function*() {
703
+ * const result = yield* Effect.dropWhile(numbers, predicate)
704
+ * console.log(result)
705
+ * })
706
+ *
707
+ * Effect.runFork(program)
708
+ * // Output: [4, 5, 6]
709
+ * ```
490
710
  *
491
711
  * @since 2.0.0
492
712
  * @category Collecting
493
713
  */
494
714
  export const dropWhile = effect.dropWhile;
495
715
  /**
496
- * Determines whether all elements of the `Collection<A>` satisfies the effectual
497
- * predicate `f`.
716
+ * Takes elements from a collection until the effectful predicate returns
717
+ * `true`.
718
+ *
719
+ * **Details**
720
+ *
721
+ * This function processes a collection of elements and uses an effectful
722
+ * predicate to decide when to stop taking elements. The elements are taken from
723
+ * the beginning of the collection until the predicate returns `true`.
724
+ *
725
+ * The predicate is a function that takes an element and its index in the
726
+ * collection, and returns an effect that resolves to a boolean.
727
+ *
728
+ * Once the predicate returns `true`, the remaining elements of the collection
729
+ * are discarded, and the function stops taking more elements.
730
+ *
731
+ * **Note**: The first element for which the predicate returns `true` is also
732
+ * included in the result.
733
+ *
734
+ * **When to Use**
735
+ *
736
+ * Use this function when you want to conditionally take elements from a
737
+ * collection based on a dynamic condition. For example, you may want to collect
738
+ * numbers from a list until a certain threshold is reached, or gather items
739
+ * until a specific condition is met.
740
+ *
741
+ * @see {@link takeWhile} for a similar function that takes elements while the
742
+ * predicate returns `true`.
743
+ *
744
+ * @example
745
+ * ```ts
746
+ * import { Effect } from "effect"
747
+ *
748
+ * const numbers = [1, 2, 3, 4, 5, 6]
749
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 3)
750
+ *
751
+ * const program = Effect.gen(function*() {
752
+ * const result = yield* Effect.takeUntil(numbers, predicate)
753
+ * console.log(result)
754
+ * })
755
+ *
756
+ * Effect.runFork(program)
757
+ * // Output: [ 1, 2, 3, 4 ]
758
+ * ```
759
+ *
760
+ * @since 2.0.0
761
+ * @category Collecting
762
+ */
763
+ export const takeUntil = effect.takeUntil;
764
+ /**
765
+ * Takes elements as long as the predicate returns `true`.
766
+ *
767
+ * **Details**
768
+ *
769
+ * This function processes a collection of elements and uses a predicate to
770
+ * decide whether to take an element.
771
+ *
772
+ * The predicate is a function that takes an element and its index, and it
773
+ * returns an effect that evaluates to a boolean.
774
+ *
775
+ * As long as the predicate returns `true`, elements will continue to be taken
776
+ * from the collection.
777
+ *
778
+ * Once the predicate returns `false`, the remaining elements are discarded.
779
+ *
780
+ * @see {@link takeUntil} for a similar function that takes elements until the predicate returns `true`.
781
+ *
782
+ * @example
783
+ * ```ts
784
+ * import { Effect } from "effect"
785
+ *
786
+ * const numbers = [1, 2, 3, 4, 5, 6]
787
+ * const predicate = (n: number, i: number) => Effect.succeed(n <= 3)
788
+ *
789
+ * const program = Effect.gen(function*() {
790
+ * const result = yield* Effect.takeWhile(numbers, predicate)
791
+ * console.log(result)
792
+ * })
793
+ *
794
+ * Effect.runFork(program)
795
+ * // Output: [1, 2, 3]
796
+ * ```
797
+ *
798
+ * @since 2.0.0
799
+ * @category Collecting
800
+ */
801
+ export const takeWhile = effect.takeWhile;
802
+ /**
803
+ * Determines whether all elements of the iterable satisfy the effectful
804
+ * predicate.
805
+ *
806
+ * **Details**
807
+ *
808
+ * This function checks whether every element in a given collection (an
809
+ * iterable) satisfies a condition defined by an effectful predicate.
810
+ *
811
+ * The predicate is a function that takes an element and its index, and it
812
+ * returns an effect that evaluates to a boolean.
813
+ *
814
+ * The function will process each element and return `true` if all elements
815
+ * satisfy the predicate; otherwise, it returns `false`.
816
+ *
817
+ * **When to Use**
818
+ *
819
+ * This function is useful when you need to verify that all items in a
820
+ * collection meet certain criteria, even when the evaluation of each item
821
+ * involves effects, such as asynchronous checks or complex computations.
822
+ *
823
+ * @see {@link exists} for a similar function that returns a boolean indicating
824
+ * whether **any** element satisfies the predicate.
825
+ *
826
+ * @example
827
+ * ```ts
828
+ * import { Effect } from "effect"
829
+ *
830
+ * const numbers = [2, 4, 6, 8]
831
+ * const predicate = (n: number, i: number) => Effect.succeed(n % 2 === 0)
832
+ *
833
+ * const program = Effect.gen(function*() {
834
+ * const allEven = yield* Effect.every(numbers, predicate)
835
+ * console.log(allEven)
836
+ * })
837
+ *
838
+ * Effect.runFork(program)
839
+ * // Output: true
840
+ * ```
498
841
  *
499
842
  * @since 2.0.0
500
843
  * @category Condition Checking
501
844
  */
502
845
  export const every = effect.every;
503
846
  /**
504
- * Determines whether any element of the `Iterable<A>` satisfies the effectual
505
- * predicate `f`.
847
+ * Determines whether any element of the iterable satisfies the effectual
848
+ * predicate.
849
+ *
850
+ * **Details**
851
+ *
852
+ * This function checks whether any element in a given collection (an iterable)
853
+ * satisfies a condition defined by an effectful predicate.
854
+ *
855
+ * The predicate is a function that takes an element and its index, and it
856
+ * returns an effect that evaluates to a boolean.
857
+ *
858
+ * The function will process each element, and if any element satisfies the
859
+ * predicate (returns `true`), the function will immediately return `true`.
860
+ *
861
+ * If none of the elements satisfy the condition, it will return `false`.
862
+ *
863
+ * **When to Use**
864
+ *
865
+ * This function allows you to quickly check for a condition in a collection
866
+ * without having to manually iterate over it.
867
+ *
868
+ * @see {@link every} for a similar function that checks if **all** elements
869
+ * satisfy the predicate.
870
+ *
871
+ * @example
872
+ * ```ts
873
+ * import { Effect } from "effect"
874
+ *
875
+ * const numbers = [1, 2, 3, 4]
876
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 2)
877
+ *
878
+ * const program = Effect.gen(function*() {
879
+ * const hasLargeNumber = yield* Effect.exists(numbers, predicate)
880
+ * console.log(hasLargeNumber)
881
+ * })
882
+ *
883
+ * Effect.runFork(program)
884
+ * // Output: true
885
+ * ```
506
886
  *
507
887
  * @since 2.0.0
508
888
  * @category Condition Checking
509
889
  */
510
890
  export const exists = fiberRuntime.exists;
511
891
  /**
512
- * Filters the collection using the specified effectful predicate.
892
+ * Filters an iterable using the specified effectful predicate.
893
+ *
894
+ * **Details**
895
+ *
896
+ * This function filters a collection (an iterable) by applying an effectful
897
+ * predicate.
898
+ *
899
+ * The predicate is a function that takes an element and its index, and it
900
+ * returns an effect that evaluates to a boolean.
901
+ *
902
+ * The function processes each element in the collection and keeps only those
903
+ * that satisfy the condition defined by the predicate.
904
+ *
905
+ * **Options**
906
+ *
907
+ * You can also adjust the behavior with options such as concurrency, batching,
908
+ * or whether to negate the condition.
909
+ *
910
+ * **When to Use**
911
+ *
912
+ * This function allows you to selectively keep or remove elements based on a
913
+ * condition that may involve asynchronous or side-effect-causing operations.
914
+ *
915
+ * @example
916
+ * ```ts
917
+ * import { Effect } from "effect"
918
+ *
919
+ * const numbers = [1, 2, 3, 4, 5]
920
+ * const predicate = (n: number, i: number) => Effect.succeed(n % 2 === 0)
921
+ *
922
+ * const program = Effect.gen(function*() {
923
+ * const result = yield* Effect.filter(numbers, predicate)
924
+ * console.log(result)
925
+ * })
926
+ *
927
+ * Effect.runFork(program)
928
+ * // Output: [2, 4]
929
+ * ```
513
930
  *
514
931
  * @since 2.0.0
515
932
  * @category Filtering
@@ -523,8 +940,6 @@ export const filter = fiberRuntime.filter;
523
940
  * element is kept; if it returns `None`, the element is removed. The operation
524
941
  * is done sequentially for each element.
525
942
  *
526
- * @see {@link filter} for concurrent filtering without mapping.
527
- *
528
943
  * @example
529
944
  * ```ts
530
945
  * import { Console, Effect, Option } from "effect"
@@ -556,6 +971,41 @@ export const filterMap = effect.filterMap;
556
971
  /**
557
972
  * Returns the first element that satisfies the effectful predicate.
558
973
  *
974
+ * **Details**
975
+ *
976
+ * This function processes a collection of elements and applies an effectful
977
+ * predicate to each element.
978
+ *
979
+ * The predicate is a function that takes an element and its index in the
980
+ * collection, and it returns an effect that evaluates to a boolean.
981
+ *
982
+ * The function stops as soon as it finds the first element for which the
983
+ * predicate returns `true` and returns that element wrapped in an `Option`.
984
+ *
985
+ * If no element satisfies the predicate, the result will be `None`.
986
+ *
987
+ * **When to Use**
988
+ *
989
+ * This function allows you to efficiently find an element that meets a specific
990
+ * condition, even when the evaluation involves effects like asynchronous
991
+ * operations or side effects.
992
+ *
993
+ * @example
994
+ * ```ts
995
+ * import { Effect } from "effect"
996
+ *
997
+ * const numbers = [1, 2, 3, 4, 5]
998
+ * const predicate = (n: number, i: number) => Effect.succeed(n > 3)
999
+ *
1000
+ * const program = Effect.gen(function*() {
1001
+ * const result = yield* Effect.findFirst(numbers, predicate)
1002
+ * console.log(result)
1003
+ * })
1004
+ *
1005
+ * Effect.runFork(program)
1006
+ * // Output: { _id: 'Option', _tag: 'Some', value: 4 }
1007
+ * ```
1008
+ *
559
1009
  * @since 2.0.0
560
1010
  * @category Collecting
561
1011
  */
@@ -565,8 +1015,8 @@ export const findFirst = effect.findFirst;
565
1015
  *
566
1016
  * **Details**
567
1017
  *
568
- * The `forEach` function applies a provided operation to each element in the
569
- * iterable, producing a new effect that returns an array of results.
1018
+ * This function applies a provided operation to each element in the iterable,
1019
+ * producing a new effect that returns an array of results.
570
1020
  *
571
1021
  * If any effect fails, the iteration stops immediately (short-circuiting), and
572
1022
  * the error is propagated.
@@ -628,32 +1078,99 @@ export const findFirst = effect.findFirst;
628
1078
  */
629
1079
  export const forEach = fiberRuntime.forEach;
630
1080
  /**
631
- * Returns a successful effect with the head of the collection if the collection
632
- * is non-empty, or fails with the error `None` if the collection is empty.
1081
+ * Returns the first element of the iterable if the collection is non-empty, or
1082
+ * fails with the error `NoSuchElementException` if the collection is empty.
1083
+ *
1084
+ * **When to Use**
1085
+ *
1086
+ * This function is useful when you need to retrieve the first item from a
1087
+ * collection and want to handle the case where the collection might be empty
1088
+ * without causing an unhandled exception.
1089
+ *
1090
+ * @example
1091
+ * ```ts
1092
+ * import { Effect } from "effect"
1093
+ *
1094
+ * // Simulate an async operation
1095
+ * const fetchNumbers = Effect.succeed([1, 2, 3]).pipe(Effect.delay("100 millis"))
1096
+ *
1097
+ * const program = Effect.gen(function*() {
1098
+ * const firstElement = yield* Effect.head(fetchNumbers)
1099
+ * console.log(firstElement)
1100
+ * })
1101
+ *
1102
+ * Effect.runFork(program)
1103
+ * // Output: 1
1104
+ * ```
633
1105
  *
634
1106
  * @since 2.0.0
635
1107
  * @category Collecting
636
1108
  */
637
1109
  export const head = effect.head;
638
1110
  /**
639
- * Merges an `Iterable<Effect<A, E, R>>` to a single effect, working
640
- * sequentially.
1111
+ * Merges an `Iterable<Effect<A, E, R>>` to a single effect.
1112
+ *
1113
+ * **Details**
1114
+ *
1115
+ * This function takes an iterable of effects and combines them into a single
1116
+ * effect. It does this by iterating over each effect in the collection and
1117
+ * applying a function that accumulates results into a "zero" value, which
1118
+ * starts with an initial value and is updated with each effect's success.
1119
+ *
1120
+ * The provided function `f` is called for each element in the iterable,
1121
+ * allowing you to specify how to combine the results.
1122
+ *
1123
+ * **Options**
1124
+ *
1125
+ * The function also allows you to customize how the effects are handled by
1126
+ * specifying options such as concurrency, batching, and how finalizers behave.
1127
+ * These options provide flexibility in running the effects concurrently or
1128
+ * adjusting other execution details.
1129
+ *
1130
+ * @example
1131
+ * ```ts
1132
+ * import { Effect } from "effect"
1133
+ *
1134
+ * const numbers = [Effect.succeed(1), Effect.succeed(2), Effect.succeed(3)]
1135
+ * const add = (sum: number, value: number, i: number) => sum + value
1136
+ * const zero = 0
1137
+ *
1138
+ * const program = Effect.gen(function*() {
1139
+ * const total = yield* Effect.mergeAll(numbers, zero, add)
1140
+ * console.log(total)
1141
+ * })
1142
+ *
1143
+ * Effect.runFork(program)
1144
+ * // Output: 6
1145
+ * ```
641
1146
  *
642
1147
  * @since 2.0.0
643
1148
  * @category Collecting
644
1149
  */
645
1150
  export const mergeAll = fiberRuntime.mergeAll;
646
1151
  /**
647
- * The `partition` function processes an iterable and applies an
648
- * effectful function to each element, categorizing the results into successes
649
- * and failures.
1152
+ * Processes an iterable and applies an effectful function to each element,
1153
+ * categorizing the results into successes and failures.
1154
+ *
1155
+ * **Details**
650
1156
  *
651
- * This function returns a tuple where the first part contains all the failures
652
- * and the second part contains all the successes. It's useful when you need to
653
- * separate successful outcomes from failures, allowing you to handle them
654
- * differently. The function allows the entire collection to be processed
655
- * without halting on failures, and failures are collected in a separate list
656
- * while the successes are processed normally.
1157
+ * This function processes each element in the provided iterable by applying an
1158
+ * effectful function to it. The results are then categorized into two separate
1159
+ * lists: one for failures and another for successes. This separation allows you
1160
+ * to handle the two categories differently. Failures are collected in a list
1161
+ * without interrupting the processing of the remaining elements, so the
1162
+ * operation continues even if some elements fail. This is particularly useful
1163
+ * when you need to handle both successful and failed results separately,
1164
+ * without stopping the entire process on encountering a failure.
1165
+ *
1166
+ * **When to Use**
1167
+ *
1168
+ * Use this function when you want to process a collection of items and handle
1169
+ * errors or failures without interrupting the processing of other items. It's
1170
+ * useful when you need to distinguish between successful and failed results and
1171
+ * process them separately, for example, when logging errors while continuing to
1172
+ * work with valid data. The function ensures that failures are captured, while
1173
+ * successes are processed normally.
657
1174
  *
658
1175
  * @see {@link validateAll} for a function that either collects all failures or all successes.
659
1176
  * @see {@link validateFirst} for a function that stops at the first success.
@@ -682,78 +1199,309 @@ export const mergeAll = fiberRuntime.mergeAll;
682
1199
  */
683
1200
  export const partition = fiberRuntime.partition;
684
1201
  /**
685
- * Folds an `Iterable<A>` using an effectual function f, working sequentially
686
- * from left to right.
1202
+ * Reduces an `Iterable<A>` using an effectual function `f`, working
1203
+ * sequentially from left to right.
1204
+ *
1205
+ * **Details**
1206
+ *
1207
+ * This function takes an iterable and applies a function `f` to each element in
1208
+ * the iterable. The function works sequentially, starting with an initial value
1209
+ * `zero` and then combining it with each element in the collection. The
1210
+ * provided function `f` is called for each element in the iterable, allowing
1211
+ * you to accumulate a result based on the current value and the element being
1212
+ * processed.
1213
+ *
1214
+ * **When to Use**
1215
+ *
1216
+ * The function is often used for operations like summing a collection of
1217
+ * numbers or combining results from multiple tasks. It ensures that operations
1218
+ * are performed one after the other, maintaining the order of the elements.
1219
+ *
1220
+ * @see {@link reduceWhile} for a similar function that stops the process based on a predicate.
1221
+ * @see {@link reduceRight} for a similar function that works from right to left.
1222
+ *
1223
+ * @example
1224
+ * ```ts
1225
+ * import { Console, Effect } from "effect"
1226
+ *
1227
+ * const processOrder = (id: number) =>
1228
+ * Effect.succeed({ id, price: 100 * id })
1229
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1230
+ *
1231
+ * const program = Effect.reduce(
1232
+ * [1, 2, 3, 4],
1233
+ * 0,
1234
+ * (acc, id, i) =>
1235
+ * processOrder(id)
1236
+ * .pipe(Effect.map((order) => acc + order.price))
1237
+ * )
1238
+ *
1239
+ * Effect.runPromise(program).then(console.log)
1240
+ * // Output:
1241
+ * // Order 1 processed
1242
+ * // Order 2 processed
1243
+ * // Order 3 processed
1244
+ * // Order 4 processed
1245
+ * // 1000
1246
+ * ```
687
1247
  *
688
1248
  * @since 2.0.0
689
1249
  * @category Collecting
690
1250
  */
691
1251
  export const reduce = effect.reduce;
692
1252
  /**
693
- * Reduces an `Iterable<Effect<A, E, R>>` to a single effect.
1253
+ * Reduces an `Iterable<A>` using an effectual function `body`, working
1254
+ * sequentially from left to right, stopping the process early when the
1255
+ * predicate `while` is not satisfied.
1256
+ *
1257
+ * **Details**
1258
+ *
1259
+ * This function processes a collection of elements, applying a function `body`
1260
+ * to reduce them to a single value, starting from the first element. It checks
1261
+ * the value of the accumulator against a predicate (`while`). If at any point
1262
+ * the predicate returns `false`, the reduction stops, and the accumulated
1263
+ * result is returned.
1264
+ *
1265
+ * **When to Use**
1266
+ *
1267
+ * Use this function when you need to reduce a collection of elements, but only
1268
+ * continue the process as long as a certain condition holds true. For example,
1269
+ * if you want to sum values in a list but stop as soon as the sum exceeds a
1270
+ * certain threshold, you can use this function.
1271
+ *
1272
+ * @example
1273
+ * ```ts
1274
+ * import { Console, Effect } from "effect"
1275
+ *
1276
+ * const processOrder = (id: number) =>
1277
+ * Effect.succeed({ id, price: 100 * id })
1278
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1279
+ *
1280
+ * const program = Effect.reduceWhile(
1281
+ * [1, 2, 3, 4],
1282
+ * 0,
1283
+ * {
1284
+ * body: (acc, id, i) =>
1285
+ * processOrder(id)
1286
+ * .pipe(Effect.map((order) => acc + order.price)),
1287
+ * while: (acc) => acc < 500
1288
+ * }
1289
+ * )
1290
+ *
1291
+ * Effect.runPromise(program).then(console.log)
1292
+ * // Output:
1293
+ * // Order 1 processed
1294
+ * // Order 2 processed
1295
+ * // Order 3 processed
1296
+ * // 600
1297
+ * ```
694
1298
  *
695
1299
  * @since 2.0.0
696
1300
  * @category Collecting
697
1301
  */
698
- export const reduceEffect = fiberRuntime.reduceEffect;
1302
+ export const reduceWhile = effect.reduceWhile;
699
1303
  /**
700
- * Folds an `Iterable<A>` using an effectual function f, working sequentially from left to right.
1304
+ * Reduces an `Iterable<A>` using an effectual function `f`, working
1305
+ * sequentially from right to left.
1306
+ *
1307
+ * **Details**
1308
+ *
1309
+ * This function takes an iterable and applies a function `f` to each element in
1310
+ * the iterable. The function works sequentially, starting with an initial value
1311
+ * `zero` and then combining it with each element in the collection. The
1312
+ * provided function `f` is called for each element in the iterable, allowing
1313
+ * you to accumulate a result based on the current value and the element being
1314
+ * processed.
1315
+ *
1316
+ * **When to Use**
1317
+ *
1318
+ * The function is often used for operations like summing a collection of
1319
+ * numbers or combining results from multiple tasks. It ensures that operations
1320
+ * are performed one after the other, maintaining the order of the elements.
1321
+ *
1322
+ * @see {@link reduce} for a similar function that works from left to right.
1323
+ *
1324
+ * @example
1325
+ * ```ts
1326
+ * import { Console, Effect } from "effect"
1327
+ *
1328
+ * const processOrder = (id: number) =>
1329
+ * Effect.succeed({ id, price: 100 * id })
1330
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1331
+ *
1332
+ * const program = Effect.reduceRight(
1333
+ * [1, 2, 3, 4],
1334
+ * 0,
1335
+ * (id, acc, i) =>
1336
+ * processOrder(id)
1337
+ * .pipe(Effect.map((order) => acc + order.price))
1338
+ * )
1339
+ *
1340
+ * Effect.runPromise(program).then(console.log)
1341
+ * // Output:
1342
+ * // Order 4 processed
1343
+ * // Order 3 processed
1344
+ * // Order 2 processed
1345
+ * // Order 1 processed
1346
+ * // 1000
1347
+ * ```
701
1348
  *
702
1349
  * @since 2.0.0
703
1350
  * @category Collecting
704
1351
  */
705
1352
  export const reduceRight = effect.reduceRight;
706
1353
  /**
707
- * Folds over the elements in this chunk from the left, stopping the fold early
708
- * when the predicate is not satisfied.
1354
+ * Reduces an `Iterable<Effect<A, E, R>>` to a single effect.
1355
+ *
1356
+ * **Details**
1357
+ *
1358
+ * This function processes a collection of effects and combines them into one
1359
+ * single effect. It starts with an initial effect (`zero`) and applies a
1360
+ * function `f` to each element in the collection.
1361
+ *
1362
+ * **Options**
1363
+ *
1364
+ * The function also allows you to customize how the effects are handled by
1365
+ * specifying options such as concurrency, batching, and how finalizers behave.
1366
+ * These options provide flexibility in running the effects concurrently or
1367
+ * adjusting other execution details.
1368
+ *
1369
+ * @example
1370
+ * ```ts
1371
+ * import { Console, Effect } from "effect"
1372
+ *
1373
+ * const processOrder = (id: number) =>
1374
+ * Effect.succeed({ id, price: 100 * id })
1375
+ * .pipe(Effect.tap(() => Console.log(`Order ${id} processed`)), Effect.delay(500 - (id * 100)))
1376
+ *
1377
+ * const program = Effect.reduceEffect(
1378
+ * [processOrder(1), processOrder(2), processOrder(3), processOrder(4)],
1379
+ * Effect.succeed(0),
1380
+ * (acc, order, i) => acc + order.price
1381
+ * )
1382
+ *
1383
+ * Effect.runPromise(program).then(console.log)
1384
+ * // Output:
1385
+ * // Order 1 processed
1386
+ * // Order 2 processed
1387
+ * // Order 3 processed
1388
+ * // Order 4 processed
1389
+ * // 1000
1390
+ * ```
709
1391
  *
710
1392
  * @since 2.0.0
711
1393
  * @category Collecting
712
1394
  */
713
- export const reduceWhile = effect.reduceWhile;
1395
+ export const reduceEffect = fiberRuntime.reduceEffect;
714
1396
  /**
715
1397
  * Replicates the given effect `n` times.
716
1398
  *
1399
+ * **Details**
1400
+ *
1401
+ * This function takes an effect and replicates it a specified number of times
1402
+ * (`n`). The result is an array of `n` effects, each of which is identical to
1403
+ * the original effect.
1404
+ *
1405
+ * @example
1406
+ * ```ts
1407
+ * import { Console, Effect } from "effect"
1408
+ *
1409
+ * const task = Effect.succeed("Hello, World!").pipe(
1410
+ * Effect.tap(Console.log)
1411
+ * )
1412
+ *
1413
+ * const program = Effect.gen(function*() {
1414
+ * // Replicate the task 3 times
1415
+ * const tasks = Effect.replicate(task, 3)
1416
+ * for (const t of tasks) {
1417
+ * // Run each task
1418
+ * yield* t
1419
+ * }
1420
+ * })
1421
+ *
1422
+ * Effect.runFork(program)
1423
+ * // Output:
1424
+ * // Hello, World!
1425
+ * // Hello, World!
1426
+ * // Hello, World!
1427
+ * ```
1428
+ *
717
1429
  * @since 2.0.0
718
1430
  */
719
1431
  export const replicate = fiberRuntime.replicate;
720
1432
  /**
721
- * Performs this effect the specified number of times and collects the
722
- * results.
1433
+ * Performs this effect the specified number of times and collects the results.
1434
+ *
1435
+ * **Details**
1436
+ *
1437
+ * This function repeats an effect multiple times and collects the results into
1438
+ * an array. You specify how many times to execute the effect, and it runs that
1439
+ * many times, either in sequence or concurrently depending on the provided
1440
+ * options.
1441
+ *
1442
+ * **Options**
1443
+ *
1444
+ * If the `discard` option is set to `true`, the intermediate results are not
1445
+ * collected, and the final result of the operation is `void`.
1446
+ *
1447
+ * The function also allows you to customize how the effects are handled by
1448
+ * specifying options such as concurrency, batching, and how finalizers behave.
1449
+ * These options provide flexibility in running the effects concurrently or
1450
+ * adjusting other execution details.
1451
+ *
1452
+ * @example
1453
+ * ```ts
1454
+ * import { Console, Effect } from "effect"
1455
+ *
1456
+ * let counter = 0
1457
+ *
1458
+ * const task = Effect.sync(() => ++counter).pipe(
1459
+ * Effect.tap(() => Console.log(`Task completed`))
1460
+ * )
1461
+ *
1462
+ * const program = Effect.gen(function*() {
1463
+ * // Replicate the task 3 times and collect the results
1464
+ * const results = yield* Effect.replicateEffect(task, 3)
1465
+ * yield* Console.log(`Results: ${results.join(", ")}`)
1466
+ * })
1467
+ *
1468
+ * Effect.runFork(program)
1469
+ * // Output:
1470
+ * // Task completed
1471
+ * // Task completed
1472
+ * // Task completed
1473
+ * // Results: 1, 2, 3
1474
+ * ```
723
1475
  *
724
1476
  * @since 2.0.0
725
1477
  * @category Collecting
726
1478
  */
727
1479
  export const replicateEffect = fiberRuntime.replicateEffect;
728
1480
  /**
729
- * Takes elements until the effectual predicate returns true.
1481
+ * Applies an effectful operation to each element in a collection while
1482
+ * collecting both successes and failures.
730
1483
  *
731
- * @since 2.0.0
732
- * @category Collecting
733
- */
734
- export const takeUntil = effect.takeUntil;
735
- /**
736
- * Takes all elements so long as the effectual predicate returns true.
1484
+ * **Details**
737
1485
  *
738
- * @since 2.0.0
739
- * @category Collecting
740
- */
741
- export const takeWhile = effect.takeWhile;
742
- /**
743
- * The `validateAll` function allows you to apply an effectful operation
744
- * to each element of a collection, while collecting both the successes and
745
- * failures. Unlike {@link forEach}, which would stop at the first error,
746
- * `validateAll` continues processing all elements, accumulating both
747
- * successes and failures.
1486
+ * This function allows you to apply an effectful operation to every item in a
1487
+ * collection.
748
1488
  *
749
- * This function transforms all elements of the collection using the provided
750
- * effectful operation. If any elements fail, the errors are captured and
751
- * included in the result, alongside the successful results. However, if there
752
- * are any errors, all successes are lost in the final result, which is an
753
- * important consideration when using this function.
1489
+ * Unlike {@link forEach}, which would stop at the first error, this function
1490
+ * continues processing all elements, accumulating both successes and failures.
1491
+ *
1492
+ * **When to Use**
1493
+ *
1494
+ * Use this function when you want to process every item in a collection, even
1495
+ * if some items fail. This is particularly useful when you need to perform
1496
+ * operations on all elements without halting due to an error.
1497
+ *
1498
+ * Keep in mind that if there are any failures, **all successes will be lost**,
1499
+ * so this function is not suitable when you need to keep the successful results
1500
+ * in case of errors.
754
1501
  *
755
1502
  * @see {@link forEach} for a similar function that stops at the first error.
756
- * @see {@link partition} when you need to separate successes and failures instead of losing successes with errors.
1503
+ * @see {@link partition} when you need to separate successes and failures
1504
+ * instead of losing successes with errors.
757
1505
  *
758
1506
  * @example
759
1507
  * ```ts
@@ -790,19 +1538,22 @@ export const takeWhile = effect.takeWhile;
790
1538
  */
791
1539
  export const validateAll = fiberRuntime.validateAll;
792
1540
  /**
793
- * The `validateFirst` function is similar to {@link validateAll} but
794
- * with a key difference: it returns the first successful result or all errors
795
- * if none of the operations succeed.
1541
+ * This function is similar to {@link validateAll} but with a key difference: it
1542
+ * returns the first successful result or all errors if none of the operations
1543
+ * succeed.
1544
+ *
1545
+ * **Details**
796
1546
  *
797
1547
  * This function processes a collection of elements and applies an effectful
798
- * operation to each. Unlike `validateAll`, which accumulates both
799
- * successes and failures, `validateFirst` stops and returns the first
1548
+ * operation to each. Unlike {@link validateAll}, which accumulates both
1549
+ * successes and failures, `Effect.validateFirst` stops and returns the first
800
1550
  * success it encounters. If no success occurs, it returns all accumulated
801
1551
  * errors. This can be useful when you are interested in the first successful
802
1552
  * result and want to avoid processing further once a valid result is found.
803
1553
  *
804
1554
  * @see {@link validateAll} for a similar function that accumulates all results.
805
- * @see {@link firstSuccessOf} for a similar function that processes multiple effects and returns the first successful one or the last error.
1555
+ * @see {@link firstSuccessOf} for a similar function that processes multiple
1556
+ * effects and returns the first successful one or the last error.
806
1557
  *
807
1558
  * @example
808
1559
  * ```ts
@@ -831,11 +1582,6 @@ export const validateFirst = fiberRuntime.validateFirst;
831
1582
  /**
832
1583
  * Creates an `Effect` from a callback-based asynchronous function.
833
1584
  *
834
- * **When to Use**
835
- *
836
- * Use `async` when dealing with APIs that use callback-style instead of
837
- * `async/await` or `Promise`.
838
- *
839
1585
  * **Details**
840
1586
  *
841
1587
  * The `resume` function:
@@ -852,6 +1598,11 @@ export const validateFirst = fiberRuntime.validateFirst;
852
1598
  * in cases where it is known will improve diagnostics, but not affect the
853
1599
  * behavior of the returned effect.
854
1600
  *
1601
+ * **When to Use**
1602
+ *
1603
+ * Use `Effect.async` when dealing with APIs that use callback-style instead of
1604
+ * `async/await` or `Promise`.
1605
+ *
855
1606
  * @example
856
1607
  * ```ts
857
1608
  * // Title: Wrapping a Callback API
@@ -1011,16 +1762,22 @@ export const withFiberRuntime = core.withFiberRuntime;
1011
1762
  */
1012
1763
  export const fail = core.fail;
1013
1764
  /**
1765
+ * Creates an `Effect` that fails with the specified error, evaluated lazily.
1766
+ *
1014
1767
  * @since 2.0.0
1015
1768
  * @category Creating Effects
1016
1769
  */
1017
1770
  export const failSync = core.failSync;
1018
1771
  /**
1772
+ * Creates an `Effect` that fails with the specified `Cause`.
1773
+ *
1019
1774
  * @since 2.0.0
1020
1775
  * @category Creating Effects
1021
1776
  */
1022
1777
  export const failCause = core.failCause;
1023
1778
  /**
1779
+ * Creates an `Effect` that fails with the specified `Cause`, evaluated lazily.
1780
+ *
1024
1781
  * @since 2.0.0
1025
1782
  * @category Creating Effects
1026
1783
  */
@@ -1028,22 +1785,25 @@ export const failCauseSync = core.failCauseSync;
1028
1785
  /**
1029
1786
  * Creates an effect that terminates a fiber with a specified error.
1030
1787
  *
1031
- * **When to Use**
1032
- *
1033
- * Use `die` when encountering unexpected conditions in your code that should
1034
- * not be handled as regular errors but instead represent unrecoverable defects.
1035
- *
1036
1788
  * **Details**
1037
1789
  *
1038
- * The `die` function is used to signal a defect, which represents a critical
1039
- * and unexpected error in the code. When invoked, it produces an effect that
1040
- * does not handle the error and instead terminates the fiber.
1790
+ * This function is used to signal a defect, which represents a critical and
1791
+ * unexpected error in the code. When invoked, it produces an effect that does
1792
+ * not handle the error and instead terminates the fiber.
1041
1793
  *
1042
1794
  * The error channel of the resulting effect is of type `never`, indicating that
1043
1795
  * it cannot recover from this failure.
1044
1796
  *
1045
- * @see {@link dieSync} for a variant that throws a specified error, evaluated lazily.
1046
- * @see {@link dieMessage} for a variant that throws a `RuntimeException` with a message.
1797
+ * **When to Use**
1798
+ *
1799
+ * Use this function when encountering unexpected conditions in your code that
1800
+ * should not be handled as regular errors but instead represent unrecoverable
1801
+ * defects.
1802
+ *
1803
+ * @see {@link dieSync} for a variant that throws a specified error, evaluated
1804
+ * lazily.
1805
+ * @see {@link dieMessage} for a variant that throws a `RuntimeException` with a
1806
+ * message.
1047
1807
  *
1048
1808
  * @example
1049
1809
  * ```ts
@@ -1073,20 +1833,20 @@ export const die = core.die;
1073
1833
  * Creates an effect that terminates a fiber with a `RuntimeException`
1074
1834
  * containing the specified message.
1075
1835
  *
1076
- * **When to Use**
1077
- *
1078
- * Use `dieMessage` when you want to terminate a fiber due to an unrecoverable
1079
- * defect and include a clear explanation in the message.
1080
- *
1081
1836
  * **Details**
1082
1837
  *
1083
- * The `dieMessage` function is used to signal a defect, representing a critical
1084
- * and unexpected error in the code. When invoked, it produces an effect that
1838
+ * This function is used to signal a defect, representing a critical and
1839
+ * unexpected error in the code. When invoked, it produces an effect that
1085
1840
  * terminates the fiber with a `RuntimeException` carrying the given message.
1086
1841
  *
1087
1842
  * The resulting effect has an error channel of type `never`, indicating it does
1088
1843
  * not handle or recover from the error.
1089
1844
  *
1845
+ * **When to Use**
1846
+ *
1847
+ * Use this function when you want to terminate a fiber due to an unrecoverable
1848
+ * defect and include a clear explanation in the message.
1849
+ *
1090
1850
  * @see {@link die} for a variant that throws a specified error.
1091
1851
  * @see {@link dieSync} for a variant that throws a specified error, evaluated
1092
1852
  * lazily.
@@ -1118,6 +1878,8 @@ export const dieMessage = core.dieMessage;
1118
1878
  /**
1119
1879
  * Creates an effect that dies with the specified error, evaluated lazily.
1120
1880
  *
1881
+ * **Details**
1882
+ *
1121
1883
  * This function allows you to create an effect that will terminate with a fatal error.
1122
1884
  * The error is provided as a lazy argument, meaning it will only be evaluated when the effect runs.
1123
1885
  *
@@ -1133,7 +1895,7 @@ export const dieSync = core.dieSync;
1133
1895
  *
1134
1896
  * **When to Use**
1135
1897
  *
1136
- * `gen` allows you to write code that looks and behaves like synchronous
1898
+ * `Effect.gen` allows you to write code that looks and behaves like synchronous
1137
1899
  * code, but it can handle asynchronous tasks, errors, and complex control flow
1138
1900
  * (like loops and conditions). It helps make asynchronous code more readable
1139
1901
  * and easier to manage.
@@ -1177,28 +1939,44 @@ export const dieSync = core.dieSync;
1177
1939
  */
1178
1940
  export const gen = core.gen;
1179
1941
  /**
1180
- * Returns an effect that will never produce anything. The moral equivalent of
1181
- * `while(true) {}`, only without the wasted CPU cycles.
1942
+ * An effect that that runs indefinitely and never produces any result. The
1943
+ * moral equivalent of `while(true) {}`, only without the wasted CPU cycles.
1944
+ *
1945
+ * **When to Use**
1946
+ *
1947
+ * It could be useful for long-running background tasks or to simulate waiting
1948
+ * behavior without actually consuming resources. This effect is ideal for cases
1949
+ * where you want to keep the program alive or in a certain state without
1950
+ * performing any active work.
1182
1951
  *
1183
1952
  * @since 2.0.0
1184
1953
  * @category Creating Effects
1185
1954
  */
1186
1955
  export const never = core.never;
1187
1956
  /**
1188
- * Requires the option produced by this value to be `None`.
1957
+ * Ensures the `Option` is `None`, returning `void`. Otherwise, raises a
1958
+ * `NoSuchElementException`.
1959
+ *
1960
+ * **Details**
1961
+ *
1962
+ * This function checks if the provided `Option` is `None`. If it is, it returns
1963
+ * an effect that produces no result (i.e., `void`). If the `Option` is not
1964
+ * `None` (i.e., it contains a value), the function will raise a
1965
+ * `NoSuchElementException` error.
1966
+ *
1967
+ * **When to Use**
1968
+ *
1969
+ * This is useful when you want to ensure that a certain value is absent (i.e.,
1970
+ * `None`) before continuing execution, and to handle cases where the value is
1971
+ * unexpectedly present.
1189
1972
  *
1190
1973
  * @since 2.0.0
1191
- * @category Creating Effects
1192
1974
  */
1193
1975
  export const none = effect.none;
1194
1976
  /**
1195
1977
  * Creates an `Effect` that represents an asynchronous computation guaranteed to
1196
1978
  * succeed.
1197
1979
  *
1198
- * **When to Use**
1199
- *
1200
- * Use `promise` when you are sure the operation will not reject.
1201
- *
1202
1980
  * **Details**
1203
1981
  *
1204
1982
  * The provided function (`thunk`) returns a `Promise` that should never reject; if it does, the error
@@ -1214,6 +1992,10 @@ export const none = effect.none;
1214
1992
  * An optional `AbortSignal` can be provided to allow for interruption of the
1215
1993
  * wrapped `Promise` API.
1216
1994
  *
1995
+ * **When to Use**
1996
+ *
1997
+ * Use this function when you are sure the operation will not reject.
1998
+ *
1217
1999
  * @see {@link tryPromise} for a version that can handle failures.
1218
2000
  *
1219
2001
  * @example
@@ -1269,6 +2051,15 @@ export const succeed = core.succeed;
1269
2051
  /**
1270
2052
  * Returns an effect which succeeds with `None`.
1271
2053
  *
2054
+ * **When to Use**
2055
+ *
2056
+ * Use this function when you need to represent the absence of a value in your
2057
+ * code, especially when working with optional data. This can be helpful when
2058
+ * you want to indicate that no result is available without throwing an error or
2059
+ * performing additional logic.
2060
+ *
2061
+ * @see {@link succeedSome} to create an effect that succeeds with a `Some` value.
2062
+ *
1272
2063
  * @since 2.0.0
1273
2064
  * @category Creating Effects
1274
2065
  */
@@ -1276,6 +2067,8 @@ export const succeedNone = effect.succeedNone;
1276
2067
  /**
1277
2068
  * Returns an effect which succeeds with the value wrapped in a `Some`.
1278
2069
  *
2070
+ * @see {@link succeedNone} for a similar function that returns `None` when the value is absent.
2071
+ *
1279
2072
  * @since 2.0.0
1280
2073
  * @category Creating Effects
1281
2074
  */
@@ -1283,16 +2076,28 @@ export const succeedSome = effect.succeedSome;
1283
2076
  /**
1284
2077
  * Delays the creation of an `Effect` until it is actually needed.
1285
2078
  *
1286
- * **When to Use**
2079
+ * **Details**
1287
2080
  *
1288
- * Use `suspend` when you need to defer the evaluation of an effect until it is required. This is particularly useful for optimizing expensive computations, managing circular dependencies, or resolving type inference issues.
2081
+ * The `Effect.suspend` function takes a thunk that represents the effect and
2082
+ * wraps it in a suspended effect. This means the effect will not be created
2083
+ * until it is explicitly needed, which is helpful in various scenarios:
2084
+ * - **Lazy Evaluation**: Helps optimize performance by deferring computations,
2085
+ * especially when the effect might not be needed, or when its computation is
2086
+ * expensive. This also ensures that any side effects or scoped captures are
2087
+ * re-executed on each invocation.
2088
+ * - **Handling Circular Dependencies**: Useful in managing circular
2089
+ * dependencies, such as recursive functions that need to avoid eager
2090
+ * evaluation to prevent stack overflow.
2091
+ * - **Unifying Return Types**: Can help TypeScript unify return types in
2092
+ * situations where multiple branches of logic return different effects,
2093
+ * simplifying type inference.
1289
2094
  *
1290
- * **Details**
2095
+ * **When to Use**
1291
2096
  *
1292
- * `suspend` takes a thunk that represents the effect and wraps it in a suspended effect. This means the effect will not be created until it is explicitly needed, which is helpful in various scenarios:
1293
- * - **Lazy Evaluation**: Helps optimize performance by deferring computations, especially when the effect might not be needed, or when its computation is expensive. This also ensures that any side effects or scoped captures are re-executed on each invocation.
1294
- * - **Handling Circular Dependencies**: Useful in managing circular dependencies, such as recursive functions that need to avoid eager evaluation to prevent stack overflow.
1295
- * - **Unifying Return Types**: Can help TypeScript unify return types in situations where multiple branches of logic return different effects, simplifying type inference.
2097
+ * Use this function when you need to defer the evaluation of an effect until it
2098
+ * is required. This is particularly useful for optimizing expensive
2099
+ * computations, managing circular dependencies, or resolving type inference
2100
+ * issues.
1296
2101
  *
1297
2102
  * @example
1298
2103
  * ```ts
@@ -1366,10 +2171,6 @@ export const suspend = core.suspend;
1366
2171
  /**
1367
2172
  * Creates an `Effect` that represents a synchronous side-effectful computation.
1368
2173
  *
1369
- * **When to Use**
1370
- *
1371
- * Use `sync` when you are sure the operation will not fail.
1372
- *
1373
2174
  * **Details**
1374
2175
  *
1375
2176
  * The provided function (`thunk`) must not throw errors; if it does, the error
@@ -1380,6 +2181,10 @@ export const suspend = core.suspend;
1380
2181
  * crash in the program, which can be further managed or logged using tools like
1381
2182
  * {@link catchAllDefect}.
1382
2183
  *
2184
+ * **When to Use**
2185
+ *
2186
+ * Use this function when you are sure the operation will not fail.
2187
+ *
1383
2188
  * @see {@link try_ | try} for a version that can handle failures.
1384
2189
  *
1385
2190
  * @example
@@ -1404,6 +2209,16 @@ export const sync = core.sync;
1404
2209
  const _void = core.void;
1405
2210
  export {
1406
2211
  /**
2212
+ * Represents an effect that does nothing and produces no value.
2213
+ *
2214
+ * **When to Use**
2215
+ *
2216
+ * Use this effect when you need to represent an effect that does nothing.
2217
+ * This is useful in scenarios where you need to satisfy an effect-based
2218
+ * interface or control program flow without performing any operations. For
2219
+ * example, it can be used in situations where you want to return an effect
2220
+ * from a function but do not need to compute or return any result.
2221
+ *
1407
2222
  * @since 2.0.0
1408
2223
  * @category Creating Effects
1409
2224
  */
@@ -1416,7 +2231,45 @@ export const yieldNow = core.yieldNow;
1416
2231
  const _catch = effect._catch;
1417
2232
  export {
1418
2233
  /**
1419
- * Recovers from specified error.
2234
+ * Recovers from a specified error by catching it and handling it with a provided function.
2235
+ *
2236
+ * **Details**
2237
+ *
2238
+ * This function allows you to recover from specific errors that occur during
2239
+ * the execution of an effect. It works by catching a specific type of error
2240
+ * (identified by a discriminator) and then handling it using a provided
2241
+ * handler function. The handler can return a new effect that helps recover
2242
+ * from the error, allowing the program to continue. If the error doesn't
2243
+ * match the specified type, the function allows the original effect to
2244
+ * continue as it was.
2245
+ *
2246
+ * @see {@link catchTag} for a version that can recover from errors based on a `_tag` discriminator.
2247
+ *
2248
+ * @example
2249
+ * ```ts
2250
+ * import { Console, Effect } from "effect"
2251
+ *
2252
+ * class NetworkError {
2253
+ * readonly _tag = "NetworkError"
2254
+ * }
2255
+ * class ValidationError {
2256
+ * readonly _tag = "ValidationError"
2257
+ * }
2258
+ *
2259
+ * // Simulate an effect that may fail
2260
+ * const task: Effect.Effect<never, NetworkError | ValidationError, never> = Effect.fail(new NetworkError())
2261
+ *
2262
+ * const program = Effect.gen(function*() {
2263
+ * const result = yield* Effect.catch(task, "_tag", {
2264
+ * failure: "NetworkError",
2265
+ * onFailure: (error) => Effect.succeed(`recovered from error: ${error._tag}`)
2266
+ * })
2267
+ * console.log(`Result: ${result}`)
2268
+ * })
2269
+ *
2270
+ * Effect.runFork(program)
2271
+ * // Output: Result: recovered from error: NetworkError
2272
+ * ```
1420
2273
  *
1421
2274
  * @since 2.0.0
1422
2275
  * @category Error handling
@@ -1427,15 +2280,16 @@ _catch as catch };
1427
2280
  *
1428
2281
  * **Details**
1429
2282
  *
1430
- * The `catchAll` function catches any errors that may occur during the
1431
- * execution of an effect and allows you to handle them by specifying a fallback
1432
- * effect. This ensures that the program continues without failing by recovering
1433
- * from errors using the provided fallback logic.
2283
+ * This function catches any errors that may occur during the execution of an
2284
+ * effect and allows you to handle them by specifying a fallback effect. This
2285
+ * ensures that the program continues without failing by recovering from errors
2286
+ * using the provided fallback logic.
1434
2287
  *
1435
- * **Note**: `catchAll` only handles recoverable errors. It will not recover
2288
+ * **Note**: This function only handles recoverable errors. It will not recover
1436
2289
  * from unrecoverable defects.
1437
2290
  *
1438
- * @see {@link catchAllCause} for a version that can recover from both recoverable and unrecoverable errors.
2291
+ * @see {@link catchAllCause} for a version that can recover from both
2292
+ * recoverable and unrecoverable errors.
1439
2293
  *
1440
2294
  * @example
1441
2295
  * ```ts
@@ -1914,12 +2768,15 @@ export const eventually = effect.eventually;
1914
2768
  /**
1915
2769
  * Discards both the success and failure values of an effect.
1916
2770
  *
1917
- * `ignore` allows you to run an effect without caring about its result,
1918
- * whether it succeeds or fails. This is useful when you only care about the
1919
- * side effects of the effect and do not need to handle or process its outcome.
2771
+ * **When to Use**
2772
+ *
2773
+ * `ignore` allows you to run an effect without caring about its result, whether
2774
+ * it succeeds or fails. This is useful when you only care about the side
2775
+ * effects of the effect and do not need to handle or process its outcome.
1920
2776
  *
1921
2777
  * @example
1922
2778
  * ```ts
2779
+ * // Title: Using Effect.ignore to Discard Values
1923
2780
  * import { Effect } from "effect"
1924
2781
  *
1925
2782
  * // ┌─── Effect<number, string, never>
@@ -2040,21 +2897,30 @@ export const sandbox = effect.sandbox;
2040
2897
  /**
2041
2898
  * Retries a failing effect based on a defined retry policy.
2042
2899
  *
2043
- * The `retry` function allows you to retry a failing effect multiple
2044
- * times according to a specified policy. This can be useful when dealing with
2045
- * intermittent failures, such as network issues or temporary resource
2046
- * unavailability. By defining a retry policy, you can control the number of
2047
- * retries, the delay between them, and when to stop retrying.
2900
+ * **Details**
2901
+ *
2902
+ * The `Effect.retry` function takes an effect and a {@link Schedule} policy,
2903
+ * and will automatically retry the effect if it fails, following the rules of
2904
+ * the policy.
2905
+ *
2906
+ * If the effect ultimately succeeds, the result will be returned.
2907
+ *
2908
+ * If the maximum retries are exhausted and the effect still fails, the failure
2909
+ * is propagated.
2910
+ *
2911
+ * **When to Use**
2048
2912
  *
2049
- * The `retry` function takes an effect and a policy, and will automatically
2050
- * retry the effect if it fails, following the rules of the policy. If the
2051
- * effect ultimately succeeds, the result will be returned. If the maximum
2052
- * retries are exhausted and the effect still fails, the failure is propagated.
2913
+ * This can be useful when dealing with intermittent failures, such as network
2914
+ * issues or temporary resource unavailability. By defining a retry policy, you
2915
+ * can control the number of retries, the delay between them, and when to stop
2916
+ * retrying.
2053
2917
  *
2054
2918
  * @see {@link retryOrElse} for a version that allows you to run a fallback.
2919
+ * @see {@link repeat} if your retry condition is based on successful outcomes rather than errors.
2055
2920
  *
2056
2921
  * @example
2057
2922
  * ```ts
2923
+ * // Title: Retrying with a Fixed Delay
2058
2924
  * import { Effect, Schedule } from "effect"
2059
2925
  *
2060
2926
  * let count = 0
@@ -2076,13 +2942,71 @@ export const sandbox = effect.sandbox;
2076
2942
  *
2077
2943
  * const repeated = Effect.retry(task, policy)
2078
2944
  *
2079
- * Effect.runPromise(repeated).then(console.log)
2945
+ * Effect.runPromise(repeated).then(console.log)
2946
+ * // Output:
2947
+ * // failure
2948
+ * // failure
2949
+ * // failure
2950
+ * // success
2951
+ * // yay!
2952
+ * ```
2953
+ *
2954
+ * @example
2955
+ * ```ts
2956
+ * // Title: Retrying a Task up to 5 times
2957
+ * import { Effect } from "effect"
2958
+ *
2959
+ * let count = 0
2960
+ *
2961
+ * // Simulates an effect with possible failures
2962
+ * const task = Effect.async<string, Error>((resume) => {
2963
+ * if (count <= 2) {
2964
+ * count++
2965
+ * console.log("failure")
2966
+ * resume(Effect.fail(new Error()))
2967
+ * } else {
2968
+ * console.log("success")
2969
+ * resume(Effect.succeed("yay!"))
2970
+ * }
2971
+ * })
2972
+ *
2973
+ * // Retry the task up to 5 times
2974
+ * Effect.runPromise(Effect.retry(task, { times: 5 }))
2080
2975
  * // Output:
2081
2976
  * // failure
2082
2977
  * // failure
2083
2978
  * // failure
2084
2979
  * // success
2085
- * // yay!
2980
+ * ```
2981
+ *
2982
+ * @example
2983
+ * ```ts
2984
+ * // Title: Retrying Until a Specific Condition is Met
2985
+ * import { Effect } from "effect"
2986
+ *
2987
+ * let count = 0
2988
+ *
2989
+ * // Define an effect that simulates varying error on each invocation
2990
+ * const action = Effect.failSync(() => {
2991
+ * console.log(`Action called ${++count} time(s)`)
2992
+ * return `Error ${count}`
2993
+ * })
2994
+ *
2995
+ * // Retry the action until a specific condition is met
2996
+ * const program = Effect.retry(action, {
2997
+ * until: (err) => err === "Error 3"
2998
+ * })
2999
+ *
3000
+ * Effect.runPromiseExit(program).then(console.log)
3001
+ * // Output:
3002
+ * // Action called 1 time(s)
3003
+ * // Action called 2 time(s)
3004
+ * // Action called 3 time(s)
3005
+ * // {
3006
+ * // _id: 'Exit',
3007
+ * // _tag: 'Failure',
3008
+ * // cause: { _id: 'Cause', _tag: 'Fail', failure: 'Error 3' }
3009
+ * // }
2086
3010
  * ```
2087
3011
  *
2088
3012
  * @since 2.0.0
@@ -2092,16 +3016,24 @@ export const retry = _schedule.retry_combined;
2092
3016
  /**
2093
3017
  * Retries a failing effect and runs a fallback effect if retries are exhausted.
2094
3018
  *
2095
- * The `retryOrElse` function attempts to retry a failing effect multiple
2096
- * times according to a defined retry policy. If the retries are exhausted and
2097
- * the effect still fails, it runs a fallback effect instead. This function is
2098
- * useful when you want to handle failures gracefully by specifying an
2099
- * alternative action after repeated failures.
3019
+ * **Details**
3020
+ *
3021
+ * The `Effect.retryOrElse` function attempts to retry a failing effect multiple
3022
+ * times according to a defined {@link Schedule} policy.
3023
+ *
3024
+ * If the retries are exhausted and the effect still fails, it runs a fallback
3025
+ * effect instead.
3026
+ *
3027
+ * **When to Use**
3028
+ *
3029
+ * This function is useful when you want to handle failures gracefully by
3030
+ * specifying an alternative action after repeated failures.
2100
3031
  *
2101
3032
  * @see {@link retry} for a version that does not run a fallback effect.
2102
3033
  *
2103
3034
  * @example
2104
3035
  * ```ts
3036
+ * // Title: Retrying with Fallback
2105
3037
  * import { Effect, Schedule, Console } from "effect"
2106
3038
  *
2107
3039
  * let count = 0
@@ -2122,8 +3054,11 @@ export const retry = _schedule.retry_combined;
2122
3054
  * const policy = Schedule.addDelay(Schedule.recurs(2), () => "100 millis")
2123
3055
  *
2124
3056
  * // If all retries fail, run the fallback effect
2125
- * const repeated = Effect.retryOrElse(task, policy, () =>
2126
- * Console.log("orElse").pipe(Effect.as("default value"))
3057
+ * const repeated = Effect.retryOrElse(
3058
+ * task,
3059
+ * policy,
3060
+ * // fallback
3061
+ * () => Console.log("orElse").pipe(Effect.as("default value"))
2127
3062
  * )
2128
3063
  *
2129
3064
  * Effect.runPromise(repeated).then(console.log)
@@ -2340,8 +3275,8 @@ export const checkInterruptible = core.checkInterruptible;
2340
3275
  * error or trigger alternative logic. This enables faster timeout handling
2341
3276
  * without waiting for the completion of the long-running task.
2342
3277
  *
2343
- * @see {@link Effect.timeout} for a version that interrupts the effect.
2344
- * @see {@link Effect.uninterruptible} for creating an uninterruptible effect.
3278
+ * @see {@link timeout} for a version that interrupts the effect.
3279
+ * @see {@link uninterruptible} for creating an uninterruptible effect.
2345
3280
  *
2346
3281
  * @example
2347
3282
  * ```ts
@@ -4229,160 +5164,572 @@ export const whenRef = effect.whenRef;
4229
5164
  * specifically with `Effect` instances, allowing you to avoid deeply nested
4230
5165
  * effect structures.
4231
5166
  *
4232
- * Since effects are immutable, `flatMap` always returns a new effect instead of
4233
- * changing the original one.
5167
+ * Since effects are immutable, `flatMap` always returns a new effect instead of
5168
+ * changing the original one.
5169
+ *
5170
+ * @example
5171
+ * ```ts
5172
+ * import { pipe, Effect } from "effect"
5173
+ *
5174
+ * // Function to apply a discount safely to a transaction amount
5175
+ * const applyDiscount = (
5176
+ * total: number,
5177
+ * discountRate: number
5178
+ * ): Effect.Effect<number, Error> =>
5179
+ * discountRate === 0
5180
+ * ? Effect.fail(new Error("Discount rate cannot be zero"))
5181
+ * : Effect.succeed(total - (total * discountRate) / 100)
5182
+ *
5183
+ * // Simulated asynchronous task to fetch a transaction amount from database
5184
+ * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5185
+ *
5186
+ * // Chaining the fetch and discount application using `flatMap`
5187
+ * const finalAmount = pipe(
5188
+ * fetchTransactionAmount,
5189
+ * Effect.flatMap((amount) => applyDiscount(amount, 5))
5190
+ * )
5191
+ *
5192
+ * Effect.runPromise(finalAmount).then(console.log)
5193
+ * // Output: 95
5194
+ * ```
5195
+ *
5196
+ * @since 2.0.0
5197
+ * @category sequencing
5198
+ */
5199
+ export const flatMap = core.flatMap;
5200
+ /**
5201
+ * Chains two actions, where the second action can depend on the result of the
5202
+ * first.
5203
+ *
5204
+ * **Syntax**
5205
+ * ```ts
5206
+ * const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
5207
+ * // or
5208
+ * const transformedEffect = Effect.andThen(myEffect, anotherEffect)
5209
+ * // or
5210
+ * const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))
5211
+ * ```
5212
+ *
5213
+ * **When to Use**
5214
+ *
5215
+ * Use `andThen` when you need to run multiple actions in sequence, with the
5216
+ * second action depending on the result of the first. This is useful for
5217
+ * combining effects or handling computations that must happen in order.
5218
+ *
5219
+ * **Details**
5220
+ *
5221
+ * The second action can be:
5222
+ *
5223
+ * - A constant value (similar to {@link as})
5224
+ * - A function returning a value (similar to {@link map})
5225
+ * - A `Promise`
5226
+ * - A function returning a `Promise`
5227
+ * - An `Effect`
5228
+ * - A function returning an `Effect` (similar to {@link flatMap})
5229
+ *
5230
+ * **Note:** `andThen` works well with both `Option` and `Either` types,
5231
+ * treating them as effects.
5232
+ *
5233
+ * @example
5234
+ * ```ts
5235
+ * // Title: Applying a Discount Based on Fetched Amount
5236
+ * import { pipe, Effect } from "effect"
5237
+ *
5238
+ * // Function to apply a discount safely to a transaction amount
5239
+ * const applyDiscount = (
5240
+ * total: number,
5241
+ * discountRate: number
5242
+ * ): Effect.Effect<number, Error> =>
5243
+ * discountRate === 0
5244
+ * ? Effect.fail(new Error("Discount rate cannot be zero"))
5245
+ * : Effect.succeed(total - (total * discountRate) / 100)
5246
+ *
5247
+ * // Simulated asynchronous task to fetch a transaction amount from database
5248
+ * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5249
+ *
5250
+ * // Using Effect.map and Effect.flatMap
5251
+ * const result1 = pipe(
5252
+ * fetchTransactionAmount,
5253
+ * Effect.map((amount) => amount * 2),
5254
+ * Effect.flatMap((amount) => applyDiscount(amount, 5))
5255
+ * )
5256
+ *
5257
+ * Effect.runPromise(result1).then(console.log)
5258
+ * // Output: 190
5259
+ *
5260
+ * // Using Effect.andThen
5261
+ * const result2 = pipe(
5262
+ * fetchTransactionAmount,
5263
+ * Effect.andThen((amount) => amount * 2),
5264
+ * Effect.andThen((amount) => applyDiscount(amount, 5))
5265
+ * )
5266
+ *
5267
+ * Effect.runPromise(result2).then(console.log)
5268
+ * // Output: 190
5269
+ * ```
5270
+ *
5271
+ * @since 2.0.0
5272
+ * @category sequencing
5273
+ */
5274
+ export const andThen = core.andThen;
5275
+ /**
5276
+ * @since 2.0.0
5277
+ * @category sequencing
5278
+ */
5279
+ export const flatten = core.flatten;
5280
+ /**
5281
+ * Races two effects and returns the result of the first successful one.
5282
+ *
5283
+ * **Details**
5284
+ *
5285
+ * This function takes two effects and runs them concurrently. The first effect
5286
+ * that successfully completes will determine the result of the race, and the
5287
+ * other effect will be interrupted.
5288
+ *
5289
+ * If neither effect succeeds, the function will fail with a `Cause`
5290
+ * containing all the errors.
5291
+ *
5292
+ * **When to Use**
5293
+ *
5294
+ * This is useful when you want to run two effects concurrently, but only care
5295
+ * about the first one to succeed. It is commonly used in cases like timeouts,
5296
+ * retries, or when you want to optimize for the faster response without
5297
+ * worrying about the other effect.
5298
+ *
5299
+ * **Handling Success or Failure with Either**
5300
+ *
5301
+ * If you want to handle the result of whichever task completes first, whether
5302
+ * it succeeds or fails, you can use the `Effect.either` function. This function
5303
+ * wraps the result in an `Either` type, allowing you to see if the result
5304
+ * was a success (`Right`) or a failure (`Left`).
5305
+ *
5306
+ * @see {@link raceAll} for a version that handles multiple effects.
5307
+ * @see {@link raceFirst} for a version that returns the result of the first effect to complete.
5308
+ *
5309
+ * @example
5310
+ * ```ts
5311
+ * // Title: Both Tasks Succeed
5312
+ * import { Effect, Console } from "effect"
5313
+ *
5314
+ * const task1 = Effect.succeed("task1").pipe(
5315
+ * Effect.delay("200 millis"),
5316
+ * Effect.tap(Console.log("task1 done")),
5317
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5318
+ * )
5319
+ * const task2 = Effect.succeed("task2").pipe(
5320
+ * Effect.delay("100 millis"),
5321
+ * Effect.tap(Console.log("task2 done")),
5322
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5323
+ * )
5324
+ *
5325
+ * const program = Effect.race(task1, task2)
5326
+ *
5327
+ * Effect.runFork(program)
5328
+ * // Output:
5329
+ * // task1 done
5330
+ * // task2 interrupted
5331
+ * ```
5332
+ *
5333
+ * @example
5334
+ * ```ts
5335
+ * // Title: One Task Fails, One Succeeds
5336
+ * import { Effect, Console } from "effect"
5337
+ *
5338
+ * const task1 = Effect.fail("task1").pipe(
5339
+ * Effect.delay("100 millis"),
5340
+ * Effect.tap(Console.log("task1 done")),
5341
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5342
+ * )
5343
+ * const task2 = Effect.succeed("task2").pipe(
5344
+ * Effect.delay("200 millis"),
5345
+ * Effect.tap(Console.log("task2 done")),
5346
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5347
+ * )
5348
+ *
5349
+ * const program = Effect.race(task1, task2)
5350
+ *
5351
+ * Effect.runFork(program)
5352
+ * // Output:
5353
+ * // task2 done
5354
+ * ```
5355
+ *
5356
+ * @example
5357
+ * ```ts
5358
+ * // Title: Both Tasks Fail
5359
+ * import { Effect, Console } from "effect"
5360
+ *
5361
+ * const task1 = Effect.fail("task1").pipe(
5362
+ * Effect.delay("100 millis"),
5363
+ * Effect.tap(Console.log("task1 done")),
5364
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5365
+ * )
5366
+ * const task2 = Effect.fail("task2").pipe(
5367
+ * Effect.delay("200 millis"),
5368
+ * Effect.tap(Console.log("task2 done")),
5369
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5370
+ * )
5371
+ *
5372
+ * const program = Effect.race(task1, task2)
5373
+ *
5374
+ * Effect.runPromiseExit(program).then(console.log)
5375
+ * // Output:
5376
+ * // {
5377
+ * // _id: 'Exit',
5378
+ * // _tag: 'Failure',
5379
+ * // cause: {
5380
+ * // _id: 'Cause',
5381
+ * // _tag: 'Parallel',
5382
+ * // left: { _id: 'Cause', _tag: 'Fail', failure: 'task1' },
5383
+ * // right: { _id: 'Cause', _tag: 'Fail', failure: 'task2' }
5384
+ * // }
5385
+ * // }
5386
+ * ```
5387
+ *
5388
+ * @example
5389
+ * ```ts
5390
+ * // Title: Handling Success or Failure with Either
5391
+ * import { Effect, Console } from "effect"
5392
+ *
5393
+ * const task1 = Effect.fail("task1").pipe(
5394
+ * Effect.delay("100 millis"),
5395
+ * Effect.tap(Console.log("task1 done")),
5396
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5397
+ * )
5398
+ * const task2 = Effect.succeed("task2").pipe(
5399
+ * Effect.delay("200 millis"),
5400
+ * Effect.tap(Console.log("task2 done")),
5401
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5402
+ * )
5403
+ *
5404
+ * // Run both tasks concurrently, wrapping the result
5405
+ * // in Either to capture success or failure
5406
+ * const program = Effect.race(Effect.either(task1), Effect.either(task2))
5407
+ *
5408
+ * Effect.runPromise(program).then(console.log)
5409
+ * // Output:
5410
+ * // task2 interrupted
5411
+ * // { _id: 'Either', _tag: 'Left', left: 'task1' }
5412
+ * ```
5413
+ *
5414
+ * @since 2.0.0
5415
+ * @category Racing
5416
+ */
5417
+ export const race = fiberRuntime.race;
5418
+ /**
5419
+ * Races multiple effects and returns the first successful result.
5420
+ *
5421
+ * **Details**
5422
+ *
5423
+ * This function runs multiple effects concurrently and returns the result of
5424
+ * the first one to succeed. If one effect succeeds, the others will be
5425
+ * interrupted.
5426
+ *
5427
+ * If none of the effects succeed, the function will fail with the last error
5428
+ * encountered.
5429
+ *
5430
+ * **When to Use**
5431
+ *
5432
+ * This is useful when you want to race multiple effects, but only care about
5433
+ * the first one to succeed. It is commonly used in cases like timeouts,
5434
+ * retries, or when you want to optimize for the faster response without
5435
+ * worrying about the other effects.
5436
+ *
5437
+ * @see {@link race} for a version that handles only two effects.
5438
+ *
5439
+ * @example
5440
+ * ```ts
5441
+ * // Title: All Tasks Succeed
5442
+ * import { Effect, Console } from "effect"
5443
+ *
5444
+ * const task1 = Effect.succeed("task1").pipe(
5445
+ * Effect.delay("100 millis"),
5446
+ * Effect.tap(Console.log("task1 done")),
5447
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5448
+ * )
5449
+ * const task2 = Effect.succeed("task2").pipe(
5450
+ * Effect.delay("200 millis"),
5451
+ * Effect.tap(Console.log("task2 done")),
5452
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5453
+ * )
5454
+ *
5455
+ * const task3 = Effect.succeed("task3").pipe(
5456
+ * Effect.delay("150 millis"),
5457
+ * Effect.tap(Console.log("task3 done")),
5458
+ * Effect.onInterrupt(() => Console.log("task3 interrupted"))
5459
+ * )
5460
+ *
5461
+ * const program = Effect.raceAll([task1, task2, task3])
5462
+ *
5463
+ * Effect.runFork(program)
5464
+ * // Output:
5465
+ * // task1 done
5466
+ * // task2 interrupted
5467
+ * // task3 interrupted
5468
+ * ```
5469
+ *
5470
+ * @example
5471
+ * ```ts
5472
+ * // Title: One Task Fails, Two Tasks Succeed
5473
+ * import { Effect, Console } from "effect"
5474
+ *
5475
+ * const task1 = Effect.fail("task1").pipe(
5476
+ * Effect.delay("100 millis"),
5477
+ * Effect.tap(Console.log("task1 done")),
5478
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5479
+ * )
5480
+ * const task2 = Effect.succeed("task2").pipe(
5481
+ * Effect.delay("200 millis"),
5482
+ * Effect.tap(Console.log("task2 done")),
5483
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5484
+ * )
5485
+ *
5486
+ * const task3 = Effect.succeed("task3").pipe(
5487
+ * Effect.delay("150 millis"),
5488
+ * Effect.tap(Console.log("task3 done")),
5489
+ * Effect.onInterrupt(() => Console.log("task3 interrupted"))
5490
+ * )
5491
+ *
5492
+ * const program = Effect.raceAll([task1, task2, task3])
5493
+ *
5494
+ * Effect.runFork(program)
5495
+ * // Output:
5496
+ * // task3 done
5497
+ * // task2 interrupted
5498
+ * ```
4234
5499
  *
4235
5500
  * @example
4236
5501
  * ```ts
4237
- * import { pipe, Effect } from "effect"
4238
- *
4239
- * // Function to apply a discount safely to a transaction amount
4240
- * const applyDiscount = (
4241
- * total: number,
4242
- * discountRate: number
4243
- * ): Effect.Effect<number, Error> =>
4244
- * discountRate === 0
4245
- * ? Effect.fail(new Error("Discount rate cannot be zero"))
4246
- * : Effect.succeed(total - (total * discountRate) / 100)
5502
+ * // Title: All Tasks Fail
5503
+ * import { Effect, Console } from "effect"
4247
5504
  *
4248
- * // Simulated asynchronous task to fetch a transaction amount from database
4249
- * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5505
+ * const task1 = Effect.fail("task1").pipe(
5506
+ * Effect.delay("100 millis"),
5507
+ * Effect.tap(Console.log("task1 done")),
5508
+ * Effect.onInterrupt(() => Console.log("task1 interrupted"))
5509
+ * )
5510
+ * const task2 = Effect.fail("task2").pipe(
5511
+ * Effect.delay("200 millis"),
5512
+ * Effect.tap(Console.log("task2 done")),
5513
+ * Effect.onInterrupt(() => Console.log("task2 interrupted"))
5514
+ * )
4250
5515
  *
4251
- * // Chaining the fetch and discount application using `flatMap`
4252
- * const finalAmount = pipe(
4253
- * fetchTransactionAmount,
4254
- * Effect.flatMap((amount) => applyDiscount(amount, 5))
5516
+ * const task3 = Effect.fail("task3").pipe(
5517
+ * Effect.delay("150 millis"),
5518
+ * Effect.tap(Console.log("task3 done")),
5519
+ * Effect.onInterrupt(() => Console.log("task3 interrupted"))
4255
5520
  * )
4256
5521
  *
4257
- * Effect.runPromise(finalAmount).then(console.log)
4258
- * // Output: 95
5522
+ * const program = Effect.raceAll([task1, task2, task3])
5523
+ *
5524
+ * Effect.runPromiseExit(program).then(console.log)
5525
+ * // Output:
5526
+ * // {
5527
+ * // _id: 'Exit',
5528
+ * // _tag: 'Failure',
5529
+ * // cause: { _id: 'Cause', _tag: 'Fail', failure: 'task2' }
5530
+ * // }
4259
5531
  * ```
4260
5532
  *
4261
5533
  * @since 2.0.0
4262
- * @category sequencing
5534
+ * @category Racing
4263
5535
  */
4264
- export const flatMap = core.flatMap;
5536
+ export const raceAll = fiberRuntime.raceAll;
4265
5537
  /**
4266
- * Chains two actions, where the second action can depend on the result of the
4267
- * first.
5538
+ * Races two effects and returns the result of the first one to complete.
4268
5539
  *
4269
- * **Syntax**
4270
- * ```ts
4271
- * const transformedEffect = pipe(myEffect, Effect.andThen(anotherEffect))
4272
- * // or
4273
- * const transformedEffect = Effect.andThen(myEffect, anotherEffect)
4274
- * // or
4275
- * const transformedEffect = myEffect.pipe(Effect.andThen(anotherEffect))
4276
- * ```
5540
+ * **Details**
5541
+ *
5542
+ * This function takes two effects and runs them concurrently, returning the
5543
+ * result of the first one that completes, regardless of whether it succeeds or
5544
+ * fails.
4277
5545
  *
4278
5546
  * **When to Use**
4279
5547
  *
4280
- * Use `andThen` when you need to run multiple actions in sequence, with the
4281
- * second action depending on the result of the first. This is useful for
4282
- * combining effects or handling computations that must happen in order.
5548
+ * This function is useful when you want to race two operations, and you want to
5549
+ * proceed with whichever one finishes first, regardless of whether it succeeds
5550
+ * or fails.
4283
5551
  *
4284
- * **Details**
5552
+ * **Disconnecting Effects**
4285
5553
  *
4286
- * The second action can be:
5554
+ * The `Effect.raceFirst` function safely interrupts the “loser” effect once the other completes, but it will not resume until the loser is cleanly terminated.
4287
5555
  *
4288
- * - A constant value (similar to {@link as})
4289
- * - A function returning a value (similar to {@link map})
4290
- * - A `Promise`
4291
- * - A function returning a `Promise`
4292
- * - An `Effect`
4293
- * - A function returning an `Effect` (similar to {@link flatMap})
5556
+ * If you want a quicker return, you can disconnect the interrupt signal for both effects. Instead of calling:
4294
5557
  *
4295
- * **Note:** `andThen` works well with both `Option` and `Either` types,
4296
- * treating them as effects.
5558
+ * ```ts
5559
+ * Effect.raceFirst(task1, task2)
5560
+ * ```
5561
+ *
5562
+ * You can use:
4297
5563
  *
4298
- * @example
4299
5564
  * ```ts
4300
- * // Title: Applying a Discount Based on Fetched Amount
4301
- * import { pipe, Effect } from "effect"
5565
+ * Effect.raceFirst(Effect.disconnect(task1), Effect.disconnect(task2))
5566
+ * ```
4302
5567
  *
4303
- * // Function to apply a discount safely to a transaction amount
4304
- * const applyDiscount = (
4305
- * total: number,
4306
- * discountRate: number
4307
- * ): Effect.Effect<number, Error> =>
4308
- * discountRate === 0
4309
- * ? Effect.fail(new Error("Discount rate cannot be zero"))
4310
- * : Effect.succeed(total - (total * discountRate) / 100)
5568
+ * This allows both effects to complete independently while still terminating the losing effect in the background.
4311
5569
  *
4312
- * // Simulated asynchronous task to fetch a transaction amount from database
4313
- * const fetchTransactionAmount = Effect.promise(() => Promise.resolve(100))
5570
+ * @example
5571
+ * ```ts
5572
+ * // Title: Both Tasks Succeed
5573
+ * import { Effect, Console } from "effect"
4314
5574
  *
4315
- * // Using Effect.map and Effect.flatMap
4316
- * const result1 = pipe(
4317
- * fetchTransactionAmount,
4318
- * Effect.map((amount) => amount * 2),
4319
- * Effect.flatMap((amount) => applyDiscount(amount, 5))
5575
+ * const task1 = Effect.succeed("task1").pipe(
5576
+ * Effect.delay("100 millis"),
5577
+ * Effect.tap(Console.log("task1 done")),
5578
+ * Effect.onInterrupt(() =>
5579
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5580
+ * )
5581
+ * )
5582
+ * const task2 = Effect.succeed("task2").pipe(
5583
+ * Effect.delay("200 millis"),
5584
+ * Effect.tap(Console.log("task2 done")),
5585
+ * Effect.onInterrupt(() =>
5586
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5587
+ * )
4320
5588
  * )
4321
5589
  *
4322
- * Effect.runPromise(result1).then(console.log)
4323
- * // Output: 190
5590
+ * const program = Effect.raceFirst(task1, task2).pipe(
5591
+ * Effect.tap(Console.log("more work..."))
5592
+ * )
4324
5593
  *
4325
- * // Using Effect.andThen
4326
- * const result2 = pipe(
4327
- * fetchTransactionAmount,
4328
- * Effect.andThen((amount) => amount * 2),
4329
- * Effect.andThen((amount) => applyDiscount(amount, 5))
5594
+ * Effect.runPromiseExit(program).then(console.log)
5595
+ * // Output:
5596
+ * // task1 done
5597
+ * // task2 interrupted
5598
+ * // more work...
5599
+ * // { _id: 'Exit', _tag: 'Success', value: 'task1' }
5600
+ * ```
5601
+ *
5602
+ * @example
5603
+ * ```ts
5604
+ * // Title: One Task Fails, One Succeeds
5605
+ * import { Effect, Console } from "effect"
5606
+ *
5607
+ * const task1 = Effect.fail("task1").pipe(
5608
+ * Effect.delay("100 millis"),
5609
+ * Effect.tap(Console.log("task1 done")),
5610
+ * Effect.onInterrupt(() =>
5611
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5612
+ * )
5613
+ * )
5614
+ * const task2 = Effect.succeed("task2").pipe(
5615
+ * Effect.delay("200 millis"),
5616
+ * Effect.tap(Console.log("task2 done")),
5617
+ * Effect.onInterrupt(() =>
5618
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5619
+ * )
4330
5620
  * )
4331
5621
  *
4332
- * Effect.runPromise(result2).then(console.log)
4333
- * // Output: 190
5622
+ * const program = Effect.raceFirst(task1, task2).pipe(
5623
+ * Effect.tap(Console.log("more work..."))
5624
+ * )
5625
+ *
5626
+ * Effect.runPromiseExit(program).then(console.log)
5627
+ * // Output:
5628
+ * // task2 interrupted
5629
+ * // {
5630
+ * // _id: 'Exit',
5631
+ * // _tag: 'Failure',
5632
+ * // cause: { _id: 'Cause', _tag: 'Fail', failure: 'task1' }
5633
+ * // }
4334
5634
  * ```
4335
5635
  *
4336
- * @since 2.0.0
4337
- * @category sequencing
4338
- */
4339
- export const andThen = core.andThen;
4340
- /**
4341
- * @since 2.0.0
4342
- * @category sequencing
4343
- */
4344
- export const flatten = core.flatten;
4345
- /**
4346
- * Returns an effect that races this effect with all the specified effects,
4347
- * yielding the value of the first effect to succeed with a value. Losers of
4348
- * the race will be interrupted immediately
5636
+ * @example
5637
+ * ```ts
5638
+ * // Title: Using Effect.disconnect for Quicker Return
5639
+ * import { Effect, Console } from "effect"
4349
5640
  *
4350
- * @since 2.0.0
4351
- * @category sequencing
4352
- */
4353
- export const raceAll = fiberRuntime.raceAll;
4354
- /**
4355
- * Returns an effect that races this effect with the specified effect,
4356
- * returning the first successful `A` from the faster side. If one effect
4357
- * succeeds, the other will be interrupted. If neither succeeds, then the
4358
- * effect will fail with some error.
5641
+ * const task1 = Effect.succeed("task1").pipe(
5642
+ * Effect.delay("100 millis"),
5643
+ * Effect.tap(Console.log("task1 done")),
5644
+ * Effect.onInterrupt(() =>
5645
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5646
+ * )
5647
+ * )
5648
+ * const task2 = Effect.succeed("task2").pipe(
5649
+ * Effect.delay("200 millis"),
5650
+ * Effect.tap(Console.log("task2 done")),
5651
+ * Effect.onInterrupt(() =>
5652
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5653
+ * )
5654
+ * )
4359
5655
  *
4360
- * @since 2.0.0
4361
- * @category sequencing
4362
- */
4363
- export const race = fiberRuntime.race;
4364
- /**
4365
- * Returns an effect that races this effect with the specified effect,
4366
- * yielding the first result to complete, whether by success or failure. If
4367
- * neither effect completes, then the composed effect will not complete.
5656
+ * // Race the two tasks with disconnect to allow quicker return
5657
+ * const program = Effect.raceFirst(
5658
+ * Effect.disconnect(task1),
5659
+ * Effect.disconnect(task2)
5660
+ * ).pipe(Effect.tap(Console.log("more work...")))
4368
5661
  *
4369
- * WARNING: The raced effect will safely interrupt the "loser", but will not
4370
- * resume until the loser has been cleanly terminated. If early return is
4371
- * desired, then instead of performing `l raceFirst r`, perform
4372
- * `l.disconnect raceFirst r.disconnect`, which disconnects left and right
4373
- * interrupt signal, allowing a fast return, with interruption performed
4374
- * in the background.
5662
+ * Effect.runPromiseExit(program).then(console.log)
5663
+ * // Output:
5664
+ * // task1 done
5665
+ * // more work...
5666
+ * // { _id: 'Exit', _tag: 'Success', value: 'task1' }
5667
+ * // task2 interrupted
5668
+ * ```
4375
5669
  *
4376
5670
  * @since 2.0.0
4377
- * @category sequencing
5671
+ * @category Racing
4378
5672
  */
4379
5673
  export const raceFirst = circular.raceFirst;
4380
5674
  /**
4381
- * Returns an effect that races this effect with the specified effect, calling
4382
- * the specified finisher as soon as one result or the other has been computed.
5675
+ * Races two effects and calls a finisher when the first one completes.
5676
+ *
5677
+ * **Details**
5678
+ *
5679
+ * This function runs two effects concurrently and calls a specified “finisher”
5680
+ * function once one of the effects completes, regardless of whether it succeeds
5681
+ * or fails.
5682
+ *
5683
+ * The finisher functions for each effect allow you to handle the results of
5684
+ * each effect as soon as they complete.
5685
+ *
5686
+ * The function takes two finisher callbacks, one for each effect, and allows
5687
+ * you to specify how to handle the result of the race.
5688
+ *
5689
+ * **When to Use**
5690
+ *
5691
+ * This function is useful when you need to react to the completion of either
5692
+ * effect without waiting for both to finish. It can be used whenever you want
5693
+ * to take action based on the first available result.
5694
+ *
5695
+ * @example
5696
+ * ```ts
5697
+ * // Title: Handling Results of Concurrent Tasks
5698
+ * import { Effect, Console } from "effect"
5699
+ *
5700
+ * const task1 = Effect.succeed("task1").pipe(
5701
+ * Effect.delay("100 millis"),
5702
+ * Effect.tap(Console.log("task1 done")),
5703
+ * Effect.onInterrupt(() =>
5704
+ * Console.log("task1 interrupted").pipe(Effect.delay("100 millis"))
5705
+ * )
5706
+ * )
5707
+ * const task2 = Effect.succeed("task2").pipe(
5708
+ * Effect.delay("200 millis"),
5709
+ * Effect.tap(Console.log("task2 done")),
5710
+ * Effect.onInterrupt(() =>
5711
+ * Console.log("task2 interrupted").pipe(Effect.delay("100 millis"))
5712
+ * )
5713
+ * )
5714
+ *
5715
+ * const program = Effect.raceWith(task1, task2, {
5716
+ * onSelfDone: (exit) => Console.log(`task1 exited with ${exit}`),
5717
+ * onOtherDone: (exit) => Console.log(`task2 exited with ${exit}`)
5718
+ * })
5719
+ *
5720
+ * Effect.runFork(program)
5721
+ * // Output:
5722
+ * // task1 done
5723
+ * // task1 exited with {
5724
+ * // "_id": "Exit",
5725
+ * // "_tag": "Success",
5726
+ * // "value": "task1"
5727
+ * // }
5728
+ * // task2 interrupted
5729
+ * ```
4383
5730
  *
4384
5731
  * @since 2.0.0
4385
- * @category sequencing
5732
+ * @category Racing
4386
5733
  */
4387
5734
  export const raceWith = fiberRuntime.raceWith;
4388
5735
  /**
@@ -4992,16 +6339,23 @@ export const isSuccess = effect.isSuccess;
4992
6339
  * Handles both success and failure cases of an effect without performing side
4993
6340
  * effects.
4994
6341
  *
6342
+ * **Details**
6343
+ *
4995
6344
  * `match` lets you define custom handlers for both success and failure
4996
6345
  * scenarios. You provide separate functions to handle each case, allowing you
4997
6346
  * to process the result if the effect succeeds, or handle the error if the
4998
- * effect fails. This is useful for structuring your code to respond differently
4999
- * to success or failure without triggering side effects.
6347
+ * effect fails.
6348
+ *
6349
+ * **When to Use**
6350
+ *
6351
+ * This is useful for structuring your code to respond differently to success or
6352
+ * failure without triggering side effects.
5000
6353
  *
5001
6354
  * @see {@link matchEffect} if you need to perform side effects in the handlers.
5002
6355
  *
5003
6356
  * @example
5004
6357
  * ```ts
6358
+ * // Title: Handling Both Success and Failure Cases
5005
6359
  * import { Effect } from "effect"
5006
6360
  *
5007
6361
  * const success: Effect.Effect<number, Error> = Effect.succeed(42)
@@ -5036,15 +6390,54 @@ export const match = effect.match;
5036
6390
  /**
5037
6391
  * Handles failures by matching the cause of failure.
5038
6392
  *
5039
- * The `matchCause` function allows you to handle failures with access to
5040
- * the full cause of the failure within a fiber. This is useful for
5041
- * differentiating between different types of errors, such as regular failures,
5042
- * defects, or interruptions. You can provide specific handling logic for each
5043
- * failure type based on the cause.
6393
+ * **Details**
6394
+ *
6395
+ * The `matchCause` function allows you to handle failures with access to the
6396
+ * full cause of the failure within a fiber.
6397
+ *
6398
+ * **When to Use**
6399
+ *
6400
+ * This is useful for differentiating between different types of errors, such as
6401
+ * regular failures, defects, or interruptions. You can provide specific
6402
+ * handling logic for each failure type based on the cause.
5044
6403
  *
5045
- * @see {@link matchCauseEffect} if you need to perform side effects in the handlers.
6404
+ * @see {@link matchCauseEffect} if you need to perform side effects in the
6405
+ * handlers.
5046
6406
  * @see {@link match} if you don't need to handle the cause of the failure.
5047
6407
  *
6408
+ * @example
6409
+ * ```ts
6410
+ * // Title: Handling Different Failure Causes
6411
+ * import { Effect } from "effect"
6412
+ *
6413
+ * const task: Effect.Effect<number, Error> = Effect.die("Uh oh!")
6414
+ *
6415
+ * const program = Effect.matchCause(task, {
6416
+ * onFailure: (cause) => {
6417
+ * switch (cause._tag) {
6418
+ * case "Fail":
6419
+ * // Handle standard failure
6420
+ * return `Fail: ${cause.error.message}`
6421
+ * case "Die":
6422
+ * // Handle defects (unexpected errors)
6423
+ * return `Die: ${cause.defect}`
6424
+ * case "Interrupt":
6425
+ * // Handle interruption
6426
+ * return `${cause.fiberId} interrupted!`
6427
+ * }
6428
+ * // Fallback for other causes
6429
+ * return "failed due to other causes"
6430
+ * },
6431
+ * onSuccess: (value) =>
6432
+ * // task completes successfully
6433
+ * `succeeded with ${value} value`
6434
+ * })
6435
+ *
6436
+ * Effect.runPromise(program).then(console.log)
6437
+ * // Output: "Die: Uh oh!"
6438
+ *
6439
+ * ```
6440
+ *
5048
6441
  * @since 2.0.0
5049
6442
  * @category getters & folding
5050
6443
  */
@@ -5052,18 +6445,21 @@ export const matchCause = core.matchCause;
5052
6445
  /**
5053
6446
  * Handles failures with access to the cause and allows performing side effects.
5054
6447
  *
5055
- * The `matchCauseEffect` function works similarly to {@link matchCause},
5056
- * but it also allows you to perform additional side effects based on the
5057
- * failure cause. This function provides access to the complete cause of the
5058
- * failure, making it possible to differentiate between various failure types,
5059
- * and allows you to respond accordingly while performing side effects (like
5060
- * logging or other operations).
6448
+ * **Details**
6449
+ *
6450
+ * The `matchCauseEffect` function works similarly to {@link matchCause}, but it
6451
+ * also allows you to perform additional side effects based on the failure
6452
+ * cause. This function provides access to the complete cause of the failure,
6453
+ * making it possible to differentiate between various failure types, and allows
6454
+ * you to respond accordingly while performing side effects (like logging or
6455
+ * other operations).
5061
6456
  *
5062
6457
  * @see {@link matchCause} if you don't need side effects and only want to handle the result or failure.
5063
6458
  * @see {@link matchEffect} if you don't need to handle the cause of the failure.
5064
6459
  *
5065
6460
  * @example
5066
6461
  * ```ts
6462
+ * // Title: Handling Different Failure Causes with Side Effects
5067
6463
  * import { Effect, Console } from "effect"
5068
6464
  *
5069
6465
  * const task: Effect.Effect<number, Error> = Effect.die("Uh oh!")
@@ -5089,7 +6485,7 @@ export const matchCause = core.matchCause;
5089
6485
  * Console.log(`succeeded with ${value} value`)
5090
6486
  * })
5091
6487
  *
5092
- * Effect.runSync(program)
6488
+ * Effect.runPromise(program)
5093
6489
  * // Output: "Die: Uh oh!"
5094
6490
  * ```
5095
6491
  *
@@ -5101,13 +6497,57 @@ export const matchCauseEffect = core.matchCauseEffect;
5101
6497
  * Handles both success and failure cases of an effect, allowing for additional
5102
6498
  * side effects.
5103
6499
  *
5104
- * The `matchEffect` function is similar to {@link match}, but it
5105
- * enables you to perform side effects in the handlers for both success and
5106
- * failure outcomes. This is useful when you need to execute additional actions,
5107
- * like logging or notifying users, based on whether an effect succeeds or
5108
- * fails.
6500
+ * **Details**
6501
+ *
6502
+ * The `matchEffect` function is similar to {@link match}, but it enables you to
6503
+ * perform side effects in the handlers for both success and failure outcomes.
6504
+ *
6505
+ * **When to Use**
6506
+ *
6507
+ * This is useful when you need to execute additional actions, like logging or
6508
+ * notifying users, based on whether an effect succeeds or fails.
6509
+ *
6510
+ * @see {@link match} if you don't need side effects and only want to handle the
6511
+ * result or failure.
6512
+ *
6513
+ * @example
6514
+ * ```ts
6515
+ * // Title: Handling Both Success and Failure Cases with Side Effects
6516
+ * import { Effect } from "effect"
6517
+ *
6518
+ * const success: Effect.Effect<number, Error> = Effect.succeed(42)
6519
+ * const failure: Effect.Effect<number, Error> = Effect.fail(
6520
+ * new Error("Uh oh!")
6521
+ * )
6522
+ *
6523
+ * const program1 = Effect.matchEffect(success, {
6524
+ * onFailure: (error) =>
6525
+ * Effect.succeed(`failure: ${error.message}`).pipe(
6526
+ * Effect.tap(Effect.log)
6527
+ * ),
6528
+ * onSuccess: (value) =>
6529
+ * Effect.succeed(`success: ${value}`).pipe(Effect.tap(Effect.log))
6530
+ * })
6531
+ *
6532
+ * console.log(Effect.runSync(program1))
6533
+ * // Output:
6534
+ * // timestamp=... level=INFO fiber=#0 message="success: 42"
6535
+ * // success: 42
6536
+ *
6537
+ * const program2 = Effect.matchEffect(failure, {
6538
+ * onFailure: (error) =>
6539
+ * Effect.succeed(`failure: ${error.message}`).pipe(
6540
+ * Effect.tap(Effect.log)
6541
+ * ),
6542
+ * onSuccess: (value) =>
6543
+ * Effect.succeed(`success: ${value}`).pipe(Effect.tap(Effect.log))
6544
+ * })
5109
6545
  *
5110
- * @see {@link match} if you don't need side effects and only want to handle the result or failure.
6546
+ * console.log(Effect.runSync(program2))
6547
+ * // Output:
6548
+ * // timestamp=... level=INFO fiber=#1 message="failure: Uh oh!"
6549
+ * // failure: Uh oh!
6550
+ * ```
5111
6551
  *
5112
6552
  * @since 2.0.0
5113
6553
  * @category getters & folding