effect 4.0.0-beta.7 → 4.0.0-beta.8

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.
package/src/Reducer.ts CHANGED
@@ -1,17 +1,107 @@
1
1
  /**
2
+ * A module for reducing collections of values into a single result.
3
+ *
4
+ * A `Reducer<A>` extends {@link Combiner.Combiner} by adding an
5
+ * `initialValue` (identity element) and a `combineAll` method that folds an
6
+ * entire collection. Think `Array.prototype.reduce`, but packaged as a
7
+ * reusable, composable value.
8
+ *
9
+ * ## Mental model
10
+ *
11
+ * - **Reducer** – a {@link Combiner.Combiner} plus an `initialValue` and a
12
+ * `combineAll` method.
13
+ * - **initialValue** – the neutral/identity element. Combining any value with
14
+ * `initialValue` should return the original value unchanged (e.g. `0` for
15
+ * addition, `""` for string concatenation).
16
+ * - **combineAll** – folds an `Iterable<A>` starting from `initialValue`.
17
+ * When omitted from {@link make}, a default left-to-right fold is used.
18
+ * - **Purity** – all reducers produced by this module are pure; they never
19
+ * mutate their arguments.
20
+ * - **Composability** – reducers can be lifted into `Option`, `Struct`,
21
+ * `Tuple`, `Record`, and other container types via helpers in those modules.
22
+ * - **Subtype of Combiner** – every `Reducer` is also a valid
23
+ * `Combiner`, so you can pass a `Reducer` anywhere a `Combiner` is
24
+ * expected.
25
+ *
26
+ * ## Common tasks
27
+ *
28
+ * - Create a reducer from a combine function and initial value → {@link make}
29
+ * - Swap argument order → {@link flip}
30
+ * - Combine two values without an initial value → use {@link Combiner.Combiner}
31
+ * instead
32
+ *
33
+ * ## Gotchas
34
+ *
35
+ * - `combineAll` on an empty iterable returns `initialValue`, not an error.
36
+ * - The default `combineAll` folds left-to-right. If your `combine` is not
37
+ * associative, order matters. Pass a custom `combineAll` to {@link make} if
38
+ * you need different traversal or short-circuiting.
39
+ * - A `Reducer` is also a valid `Combiner` — but a `Combiner` is *not* a
40
+ * `Reducer` (it lacks `initialValue`).
41
+ *
42
+ * ## Quickstart
43
+ *
44
+ * **Example** (summing a list of numbers)
45
+ *
46
+ * ```ts
47
+ * import { Reducer } from "effect"
48
+ *
49
+ * const Sum = Reducer.make<number>((a, b) => a + b, 0)
50
+ *
51
+ * console.log(Sum.combine(3, 4))
52
+ * // Output: 7
53
+ *
54
+ * console.log(Sum.combineAll([1, 2, 3, 4]))
55
+ * // Output: 10
56
+ *
57
+ * console.log(Sum.combineAll([]))
58
+ * // Output: 0
59
+ * ```
60
+ *
61
+ * ## See also
62
+ *
63
+ * - {@link make} – the primary constructor
64
+ * - {@link Reducer} – the core interface
65
+ * - {@link Combiner.Combiner} – the parent interface (no `initialValue`)
66
+ *
2
67
  * @since 4.0.0
3
68
  */
4
69
 
5
70
  import type * as Combiner from "./Combiner.ts"
6
71
 
7
72
  /**
8
- * A `Reducer` is a `Combiner` with an `initialValue` and a way to
9
- * combine a whole collection. Think `Array.prototype.reduce`, but reusable.
73
+ * Represents a strategy for reducing a collection of values of type `A` into
74
+ * a single result.
75
+ *
76
+ * Extends {@link Combiner.Combiner} with:
77
+ * - `initialValue` – the identity/neutral element for `combine`.
78
+ * - `combineAll` – folds an entire `Iterable<A>` from `initialValue`.
79
+ *
80
+ * When to use:
81
+ * - You need to fold/reduce a collection into a single value.
82
+ * - You want a reusable reducing strategy that can be passed to library
83
+ * functions like `Struct.makeReducer`, `Option.makeReducer`, or
84
+ * `Record.makeReducerUnion`.
85
+ * - You need both the combining logic *and* a known starting value.
86
+ *
87
+ * Many modules ship pre-built reducers:
88
+ * - `Number.ReducerSum`, `Number.ReducerMultiply`
89
+ * - `String.ReducerConcat`
90
+ * - `Boolean.ReducerAnd`, `Boolean.ReducerOr`
10
91
  *
11
- * Common initial values:
12
- * - numbers with addition: `0`
13
- * - strings with concatenation: `""`
14
- * - arrays with concatenation: `[]`
92
+ * **Example** (string concatenation reducer)
93
+ *
94
+ * ```ts
95
+ * import { Reducer } from "effect"
96
+ *
97
+ * const Concat = Reducer.make<string>((a, b) => a + b, "")
98
+ *
99
+ * console.log(Concat.combineAll(["hello", " ", "world"]))
100
+ * // Output: "hello world"
101
+ * ```
102
+ *
103
+ * @see {@link make} – create a `Reducer` from a function and initial value
104
+ * @see {@link Combiner.Combiner} – parent interface without `initialValue`
15
105
  *
16
106
  * @category model
17
107
  * @since 4.0.0
@@ -27,7 +117,44 @@ export interface Reducer<A> extends Combiner.Combiner<A> {
27
117
  /**
28
118
  * Creates a `Reducer` from a `combine` function and an `initialValue`.
29
119
  *
30
- * If `combineAll` is omitted, a default implementation reduces left-to-right.
120
+ * When to use:
121
+ * - You have a custom reducing operation not covered by a pre-built reducer.
122
+ * - You want to provide an optimized `combineAll` (e.g. short-circuiting on
123
+ * a known absorbing element like `0` for multiplication).
124
+ *
125
+ * Behavior:
126
+ * - If `combineAll` is omitted, a default left-to-right fold starting from
127
+ * `initialValue` is used.
128
+ * - If `combineAll` is provided, it completely replaces the default fold.
129
+ * - Pure – the returned reducer does not mutate its arguments.
130
+ *
131
+ * **Example** (multiplication with short-circuit)
132
+ *
133
+ * ```ts
134
+ * import { Reducer } from "effect"
135
+ *
136
+ * const Product = Reducer.make<number>(
137
+ * (a, b) => a * b,
138
+ * 1,
139
+ * (collection) => {
140
+ * let acc = 1
141
+ * for (const n of collection) {
142
+ * if (n === 0) return 0
143
+ * acc *= n
144
+ * }
145
+ * return acc
146
+ * }
147
+ * )
148
+ *
149
+ * console.log(Product.combineAll([2, 3, 4]))
150
+ * // Output: 24
151
+ *
152
+ * console.log(Product.combineAll([2, 0, 4]))
153
+ * // Output: 0
154
+ * ```
155
+ *
156
+ * @see {@link Reducer} – the interface this creates
157
+ * @see {@link flip} – reverse the argument order
31
158
  *
32
159
  * @since 4.0.0
33
160
  */
@@ -51,6 +178,38 @@ export function make<A>(
51
178
  }
52
179
 
53
180
  /**
181
+ * Reverses the argument order of a reducer's `combine` method.
182
+ *
183
+ * When to use:
184
+ * - You need the "right" value to act as the accumulator side.
185
+ * - You want to reverse the natural direction of a non-commutative reducer
186
+ * (e.g. string concatenation becomes prepend).
187
+ *
188
+ * Behavior:
189
+ * - Returns a new `Reducer` where `combine(self, that)` calls the original
190
+ * reducer as `combine(that, self)`.
191
+ * - The `initialValue` is preserved from the original reducer.
192
+ * - The `combineAll` is re-derived from the flipped `combine` (using the
193
+ * default left-to-right fold), not carried over from the original.
194
+ * - Does not mutate the input reducer.
195
+ *
196
+ * **Example** (reversing string concatenation)
197
+ *
198
+ * ```ts
199
+ * import { Reducer, String } from "effect"
200
+ *
201
+ * const Prepend = Reducer.flip(String.ReducerConcat)
202
+ *
203
+ * console.log(Prepend.combine("a", "b"))
204
+ * // Output: "ba"
205
+ *
206
+ * console.log(Prepend.combineAll(["a", "b", "c"]))
207
+ * // Output: "cba"
208
+ * ```
209
+ *
210
+ * @see {@link make}
211
+ * @see {@link Combiner.flip} – the same operation on a plain `Combiner`
212
+ *
54
213
  * @since 4.0.0
55
214
  */
56
215
  export function flip<A>(reducer: Reducer<A>): Reducer<A> {
package/src/index.ts CHANGED
@@ -444,6 +444,65 @@ export * as Chunk from "./Chunk.ts"
444
444
  export * as Clock from "./Clock.ts"
445
445
 
446
446
  /**
447
+ * A module for combining two values of the same type into one.
448
+ *
449
+ * A `Combiner<A>` wraps a single binary function `(self: A, that: A) => A`.
450
+ * It describes *how* two values merge but carries no initial/empty value
451
+ * (for that, see {@link Reducer} which extends `Combiner` with an
452
+ * `initialValue`).
453
+ *
454
+ * ## Mental model
455
+ *
456
+ * - **Combiner** – an object with a `combine(self, that)` method that returns
457
+ * a value of the same type.
458
+ * - **Argument order** – `self` is the "left" / accumulator side, `that` is
459
+ * the "right" / incoming side.
460
+ * - **No identity element** – unlike a monoid, a `Combiner` does not require
461
+ * a neutral element. Use {@link Reducer} when you need one.
462
+ * - **Purity** – all combiners produced by this module are pure; they never
463
+ * mutate their arguments.
464
+ * - **Composability** – combiners can be lifted into `Option`, `Struct`,
465
+ * `Tuple`, and other container types via helpers in those modules.
466
+ *
467
+ * ## Common tasks
468
+ *
469
+ * - Create a combiner from any binary function → {@link make}
470
+ * - Swap argument order → {@link flip}
471
+ * - Pick the smaller / larger of two values → {@link min} / {@link max}
472
+ * - Always keep the first or last value → {@link first} / {@link last}
473
+ * - Ignore both values and return a fixed result → {@link constant}
474
+ * - Insert a separator between combined values → {@link intercalate}
475
+ *
476
+ * ## Gotchas
477
+ *
478
+ * - `min` and `max` require an `Order<A>`, not a raw comparator. Import from
479
+ * e.g. `Number.Order` or `String.Order`.
480
+ * - `intercalate` is curried: call it with the separator first, then pass the
481
+ * base combiner.
482
+ * - A `Reducer` (which adds `initialValue`) is also a valid `Combiner` — you
483
+ * can pass a `Reducer` anywhere a `Combiner` is expected.
484
+ *
485
+ * ## Quickstart
486
+ *
487
+ * **Example** (combining strings with a separator)
488
+ *
489
+ * ```ts
490
+ * import { Combiner, String } from "effect"
491
+ *
492
+ * const csv = Combiner.intercalate(",")(String.ReducerConcat)
493
+ *
494
+ * console.log(csv.combine("a", "b"))
495
+ * // Output: "a,b"
496
+ *
497
+ * console.log(csv.combine(csv.combine("a", "b"), "c"))
498
+ * // Output: "a,b,c"
499
+ * ```
500
+ *
501
+ * ## See also
502
+ *
503
+ * - {@link make} – the primary constructor
504
+ * - {@link Combiner} – the core interface
505
+ *
447
506
  * @since 4.0.0
448
507
  */
449
508
  export * as Combiner from "./Combiner.ts"
@@ -2591,6 +2650,71 @@ export * as Redactable from "./Redactable.ts"
2591
2650
  export * as Redacted from "./Redacted.ts"
2592
2651
 
2593
2652
  /**
2653
+ * A module for reducing collections of values into a single result.
2654
+ *
2655
+ * A `Reducer<A>` extends {@link Combiner.Combiner} by adding an
2656
+ * `initialValue` (identity element) and a `combineAll` method that folds an
2657
+ * entire collection. Think `Array.prototype.reduce`, but packaged as a
2658
+ * reusable, composable value.
2659
+ *
2660
+ * ## Mental model
2661
+ *
2662
+ * - **Reducer** – a {@link Combiner.Combiner} plus an `initialValue` and a
2663
+ * `combineAll` method.
2664
+ * - **initialValue** – the neutral/identity element. Combining any value with
2665
+ * `initialValue` should return the original value unchanged (e.g. `0` for
2666
+ * addition, `""` for string concatenation).
2667
+ * - **combineAll** – folds an `Iterable<A>` starting from `initialValue`.
2668
+ * When omitted from {@link make}, a default left-to-right fold is used.
2669
+ * - **Purity** – all reducers produced by this module are pure; they never
2670
+ * mutate their arguments.
2671
+ * - **Composability** – reducers can be lifted into `Option`, `Struct`,
2672
+ * `Tuple`, `Record`, and other container types via helpers in those modules.
2673
+ * - **Subtype of Combiner** – every `Reducer` is also a valid
2674
+ * `Combiner`, so you can pass a `Reducer` anywhere a `Combiner` is
2675
+ * expected.
2676
+ *
2677
+ * ## Common tasks
2678
+ *
2679
+ * - Create a reducer from a combine function and initial value → {@link make}
2680
+ * - Swap argument order → {@link flip}
2681
+ * - Combine two values without an initial value → use {@link Combiner.Combiner}
2682
+ * instead
2683
+ *
2684
+ * ## Gotchas
2685
+ *
2686
+ * - `combineAll` on an empty iterable returns `initialValue`, not an error.
2687
+ * - The default `combineAll` folds left-to-right. If your `combine` is not
2688
+ * associative, order matters. Pass a custom `combineAll` to {@link make} if
2689
+ * you need different traversal or short-circuiting.
2690
+ * - A `Reducer` is also a valid `Combiner` — but a `Combiner` is *not* a
2691
+ * `Reducer` (it lacks `initialValue`).
2692
+ *
2693
+ * ## Quickstart
2694
+ *
2695
+ * **Example** (summing a list of numbers)
2696
+ *
2697
+ * ```ts
2698
+ * import { Reducer } from "effect"
2699
+ *
2700
+ * const Sum = Reducer.make<number>((a, b) => a + b, 0)
2701
+ *
2702
+ * console.log(Sum.combine(3, 4))
2703
+ * // Output: 7
2704
+ *
2705
+ * console.log(Sum.combineAll([1, 2, 3, 4]))
2706
+ * // Output: 10
2707
+ *
2708
+ * console.log(Sum.combineAll([]))
2709
+ * // Output: 0
2710
+ * ```
2711
+ *
2712
+ * ## See also
2713
+ *
2714
+ * - {@link make} – the primary constructor
2715
+ * - {@link Reducer} – the core interface
2716
+ * - {@link Combiner.Combiner} – the parent interface (no `initialValue`)
2717
+ *
2594
2718
  * @since 4.0.0
2595
2719
  */
2596
2720
  export * as Reducer from "./Reducer.ts"
@@ -414,7 +414,7 @@ export interface CommandOptions extends KillOptions {
414
414
  * the value of `globalThis.process.env`, prioritizing the values in `env`
415
415
  * when conflicts exist.
416
416
  */
417
- readonly env?: Record<string, string> | undefined
417
+ readonly env?: Record<string, string | undefined> | undefined
418
418
  /**
419
419
  * If set to `true`, the child process uses both the values in `env` as well
420
420
  * as the values in `globalThis.process.env`, prioritizing the values in `env`
@@ -26,7 +26,7 @@ export const findAll = <Req extends Schema.Top, Res extends Schema.Top, E, R>(
26
26
  request: Req["Encoded"]
27
27
  ): Effect.Effect<
28
28
  Array<Res["Type"]>,
29
- E | Schema.SchemaError | Cause.NoSuchElementError,
29
+ E | Schema.SchemaError,
30
30
  Req["EncodingServices"] | Res["DecodingServices"] | R
31
31
  > => Effect.flatMap(Effect.flatMap(encodeRequest(request), options.execute), decode)
32
32
  }