1/**
2 * Provides small helpers for defining and reusing TypeScript functions.
3 *
4 * The main helpers are `pipe` and `flow` for left-to-right composition and
5 * `dual` for APIs that support both direct and pipe-friendly call styles. The
6 * module also contains small identity, constant, tuple, type-level, and
7 * memoization helpers used across the library.
8 *
9 * @since 2.0.0
10 */
11import type { TypeLambda } from "./HKT.ts"
12import { pipeArguments } from "./Pipeable.ts"
13
14/**
15 * Type lambda for function types, used for higher-kinded type operations.
16 *
17 * **When to use**
18 *
19 * Use when defining higher-kinded abstractions that must accept function types
20 * as one of their type-lambda inputs.
21 *
22 * **Example** (Creating a function type with a type lambda)
23 *
24 * ```ts import.meta.vitest
25 * import type { Function, HKT } from "effect"
26 *
27 * // Create a function type using the type lambda
28 * type StringToNumber = HKT.Kind<Function.FunctionTypeLambda, string, never, never, number>
29 * // Equivalent to: (a: string) => number
30 * ```
31 *
32 * @category utility types
33 * @since 2.0.0
34 */
35export interface FunctionTypeLambda extends TypeLambda {
36 readonly type: (a: this["In"]) => this["Target"]
37}
38
39/**
40 * Creates a function that can be called in data-first style or data-last
41 * (`pipe`-friendly) style.
42 *
43 * **When to use**
44 *
45 * Use to expose one implementation through both direct and `pipe`-friendly
46 * call styles.
47 *
48 * **Details**
49 *
50 * Pass either the arity of the uncurried function or a predicate that decides
51 * whether the current call is data-first. Arity is the common case. Use a
52 * predicate when optional arguments make arity ambiguous.
53 *
54 * **Example** (Selecting data-first or data-last style by arity)
55 *
56 * ```ts import.meta.vitest
57 * import { Function, pipe } from "effect"
58 *
59 * const sum = Function.dual<
60 * (that: number) => (self: number) => number,
61 * (self: number, that: number) => number
62 * >(2, (self, that) => self + that)
63 *
64 * sum(2, 3) // => 5
65 * pipe(2, sum(3)) // => 5
66 * ```
67 *
68 * **Example** (Defining overloads with call signatures)
69 *
70 * ```ts import.meta.vitest
71 * import { Function, pipe } from "effect"
72 *
73 * const sum: {
74 * (that: number): (self: number) => number
75 * (self: number, that: number): number
76 * } = Function.dual(2, (self: number, that: number): number => self + that)
77 *
78 * sum(2, 3) // => 5
79 * pipe(2, sum(3)) // => 5
80 * ```
81 *
82 * **Example** (Selecting data-first or data-last style with a predicate)
83 *
84 * ```ts import.meta.vitest
85 * import { Function, pipe } from "effect"
86 *
87 * const sum = Function.dual<
88 * (that: number) => (self: number) => number,
89 * (self: number, that: number) => number
90 * >(
91 * (args) => args.length === 2,
92 * (self, that) => self + that
93 * )
94 *
95 * sum(2, 3) // => 5
96 * pipe(2, sum(3)) // => 5
97 * ```
98 *
99 * @category combinators
100 * @since 2.0.0
101 */
102export const dual: {
103 <DataLast extends (...args: Array<any>) => any, DataFirst extends (...args: Array<any>) => any>(
104 arity: Parameters<DataFirst>["length"],
105 body: DataFirst
106 ): DataLast & DataFirst
107 <DataLast extends (...args: Array<any>) => any, DataFirst extends (...args: Array<any>) => any>(
108 isDataFirst: (args: IArguments) => boolean,
109 body: DataFirst
110 ): DataLast & DataFirst
111} = function(arity, body) {
112 if (typeof arity === "function") {
113 return function(this: any) {
114 return arity(arguments)
115 ? body.apply(this, arguments as any)
116 : ((self: any) => body(self, ...arguments)) as any
117 }
118 }
119
120 switch (arity) {
121 case 0:
122 case 1:
123 throw new RangeError(`Invalid arity ${arity}`)
124
125 case 2:
126 return function(a, b) {
127 if (arguments.length >= 2) {
128 return body(a, b)
129 }
130 return function(self: any) {
131 return body(self, a)
132 }
133 }
134
135 case 3:
136 return function(a, b, c) {
137 if (arguments.length >= 3) {
138 return body(a, b, c)
139 }
140 return function(self: any) {
141 return body(self, a, b)
142 }
143 }
144
145 default:
146 return function() {
147 if (arguments.length >= arity) {
148 // @ts-expect-error
149 return body.apply(this, arguments)
150 }
151 const args = arguments
152 return function(self: any) {
153 return body(self, ...args)
154 }
155 }
156 }
157}
158/**
159 * Applies a function to a given value.
160 *
161 * **When to use**
162 *
163 * Use to pass a fixed value into a unary function, especially when the function
164 * is the value flowing through `pipe`.
165 *
166 * **Details**
167 *
168 * `apply(a)(f)` is equivalent to `f(a)`.
169 *
170 * **Example** (Applying an argument to a function)
171 *
172 * ```ts import.meta.vitest
173 * import { Function, pipe, String } from "effect"
174 *
175 * pipe(String.length, Function.apply("hello")) // => 5
176 * ```
177 *
178 * @see {@link pipe} for building left-to-right pipelines
179 *
180 * @category combinators
181 * @since 2.0.0
182 */
183export const apply = <A>(a: A) => <B>(self: (a: A) => B): B => self(a)
184
185/**
186 * A zero-argument function that produces a value when invoked.
187 *
188 * **When to use**
189 *
190 * Use to type a lazy value provider that should not run until called.
191 *
192 * **Example** (Creating a lazy argument)
193 *
194 * ```ts import.meta.vitest
195 * import { Function } from "effect"
196 *
197 * const constNull: Function.LazyArg<null> = Function.constant(null)
198 * constNull() // => null
199 * ```
200 *
201 * @category models
202 * @since 2.0.0
203 */
204export type LazyArg<A> = () => A
205
206/**
207 * Represents a function with multiple arguments.
208 *
209 * **When to use**
210 *
211 * Use to describe a function whose argument list is represented as a tuple
212 * type.
213 *
214 * **Example** (Typing a variadic function)
215 *
216 * ```ts import.meta.vitest
217 * import type { Function } from "effect"
218 *
219 * const sum: Function.FunctionN<[number, number], number> = (a, b) => a + b
220 * sum(2, 3) // => 5
221 * ```
222 *
223 * @category models
224 * @since 2.0.0
225 */
226export type FunctionN<A extends ReadonlyArray<unknown>, B> = (...args: A) => B
227
228/**
229 * Returns its input argument unchanged.
230 *
231 * **When to use**
232 *
233 * Use to return a value unchanged where a function is required.
234 *
235 * **Example** (Returning the same value)
236 *
237 * ```ts import.meta.vitest
238 * import { identity } from "effect"
239 *
240 * identity(5) // => 5
241 * ```
242 *
243 * @category combinators
244 * @since 2.0.0
245 */
246export const identity = <A>(a: A): A => a
247
248/**
249 * Ensures that the type of an expression matches some type,
250 * without changing the resulting type of that expression.
251 *
252 * **When to use**
253 *
254 * Use to check assignability while preserving the expression's precise inferred
255 * type.
256 *
257 * **Example** (Checking an expression against a type)
258 *
259 * ```ts import.meta.vitest
260 * import { Function } from "effect"
261 *
262 * const test1 = Function.satisfies<number>()(5 as const) // => 5
263 * // ^? const test: 5
264 * // @ts-expect-error
265 * const test2 = Function.satisfies<string>()(5)
266 * // ^? Argument of type 'number' is not assignable to parameter of type 'string'
267 * ```
268 *
269 * @see {@link cast} for changing only the static TypeScript type
270 *
271 * @category utility types
272 * @since 2.0.0
273 */
274export const satisfies = <A>() => <B extends A>(b: B) => b
275
276/**
277 * Returns the input value with a different static type.
278 *
279 * **When to use**
280 *
281 * Use when you need an explicit type-level cast and accept that the value is
282 * returned unchanged at runtime.
283 *
284 * **Gotchas**
285 *
286 * This is a type-level cast only; it performs no runtime validation or
287 * conversion.
288 *
289 * @see {@link satisfies} for checking assignability without changing the resulting type
290 *
291 * @category utility types
292 * @since 4.0.0
293 */
294export const cast: <A, B>(a: A) => B = identity as any
295
296/**
297 * Creates a zero-argument function that always returns the provided value.
298 *
299 * **When to use**
300 *
301 * Use when you need a thunk or callback that returns the same value on every
302 * invocation.
303 *
304 * **Example** (Creating a constant thunk)
305 *
306 * ```ts import.meta.vitest
307 * import { Function } from "effect"
308 *
309 * const constNull = Function.constant(null)
310 *
311 * constNull() // => null
312 * constNull() // => null
313 * ```
314 *
315 * @category constructors
316 * @since 2.0.0
317 */
318export const constant = <A>(value: A): LazyArg<A> => () => value
319
320/**
321 * Returns `true` when called.
322 *
323 * **When to use**
324 *
325 * Use when you need a thunk that returns `true` on every invocation.
326 *
327 * **Example** (Returning true from a thunk)
328 *
329 * ```ts import.meta.vitest
330 * import { Function } from "effect"
331 *
332 * Function.constTrue() // => true
333 * ```
334 *
335 * @category constants
336 * @since 2.0.0
337 */
338export const constTrue: LazyArg<boolean> = constant(true)
339
340/**
341 * Returns `false` when called.
342 *
343 * **When to use**
344 *
345 * Use when you need a thunk that returns `false` on every invocation.
346 *
347 * **Example** (Returning false from a thunk)
348 *
349 * ```ts import.meta.vitest
350 * import { Function } from "effect"
351 *
352 * Function.constFalse() // => false
353 * ```
354 *
355 * @category constants
356 * @since 2.0.0
357 */
358export const constFalse: LazyArg<boolean> = constant(false)
359
360/**
361 * Returns `null` when called.
362 *
363 * **When to use**
364 *
365 * Use when you need a thunk that returns `null` on every invocation.
366 *
367 * **Example** (Returning null from a thunk)
368 *
369 * ```ts import.meta.vitest
370 * import { Function } from "effect"
371 *
372 * Function.constNull() // => null
373 * ```
374 *
375 * @category constants
376 * @since 2.0.0
377 */
378export const constNull: LazyArg<null> = constant(null)
379
380/**
381 * Returns `undefined` when called.
382 *
383 * **When to use**
384 *
385 * Use when you need a thunk that returns `undefined` on every invocation.
386 *
387 * **Example** (Returning undefined from a thunk)
388 *
389 * ```ts import.meta.vitest
390 * import { Function } from "effect"
391 *
392 * Function.constUndefined() // => undefined
393 * ```
394 *
395 * @category constants
396 * @since 2.0.0
397 */
398export const constUndefined: LazyArg<undefined> = constant(undefined)
399
400/**
401 * Returns no meaningful value when called.
402 *
403 * **When to use**
404 *
405 * Use when you need a thunk that is called only for its effect and has no
406 * meaningful return value.
407 *
408 * **Example** (Returning void from a thunk)
409 *
410 * ```ts import.meta.vitest
411 * import { Function } from "effect"
412 *
413 * Function.constVoid() // => undefined
414 * ```
415 *
416 * @category constants
417 * @since 2.0.0
418 */
419export const constVoid: LazyArg<void> = constUndefined
420
421/**
422 * Reverses the order of arguments for a curried function.
423 *
424 * **When to use**
425 *
426 * Use to adapt a curried function when its argument groups need to be supplied
427 * in the opposite order.
428 *
429 * **Example** (Flipping curried arguments)
430 *
431 * ```ts import.meta.vitest
432 * import { Function } from "effect"
433 *
434 * const f = (a: number) => (b: string) => a - b.length
435 *
436 * Function.flip(f)("aaa")(2) // => -1
437 * ```
438 *
439 * @category combinators
440 * @since 2.0.0
441 */
442export const flip = <A extends Array<unknown>, B extends Array<unknown>, C>(
443 f: (...a: A) => (...b: B) => C
444): (...b: B) => (...a: A) => C =>
445(...b) =>
446(...a) => f(...a)(...b)
447
448/**
449 * Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
450 * The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
451 *
452 * **When to use**
453 *
454 * Use to compose exactly two unary functions into a reusable unary function.
455 *
456 * **Example** (Composing two functions)
457 *
458 * ```ts import.meta.vitest
459 * import { Function } from "effect"
460 *
461 * const increment = (n: number) => n + 1
462 * const square = (n: number) => n * n
463 *
464 * Function.compose(increment, square)(2) // => 9
465 * ```
466 *
467 * @see {@link flow} for composing a left-to-right sequence of functions
468 * @see {@link pipe} for applying a value through a left-to-right sequence immediately
469 *
470 * @category combinators
471 * @since 2.0.0
472 */
473export const compose: {
474 <B, C>(bc: (b: B) => C): <A>(self: (a: A) => B) => (a: A) => C
475 <A, B, C>(self: (a: A) => B, bc: (b: B) => C): (a: A) => C
476} = dual(2, <A, B, C>(ab: (a: A) => B, bc: (b: B) => C): (a: A) => C => (a) => bc(ab(a)))
477
478/**
479 * Marks an impossible branch by accepting a `never` value and returning any
480 * type.
481 *
482 * **When to use**
483 *
484 * Use when you need a return value in a branch that exhaustive checks prove
485 * cannot be reached.
486 *
487 * **Gotchas**
488 *
489 * Calling `absurd` throws, because a value of type `never` should be
490 * impossible at runtime.
491 *
492 * **Example** (Handling impossible values)
493 *
494 * ```ts import.meta.vitest
495 * import { absurd } from "effect"
496 *
497 * const handleNever = (value: never) => {
498 * return absurd(value) // This will throw an error if called
499 * }
500 * ```
501 *
502 * @category utility types
503 * @since 2.0.0
504 */
505export const absurd = <A>(_: never): A => {
506 throw new Error("Called `absurd` function which should be uncallable")
507}
508
509/**
510 * Creates a tupled version of this function: instead of `n` arguments, it accepts a single tuple argument.
511 *
512 * **When to use**
513 *
514 * Use to adapt a multi-argument function so it accepts one tuple argument.
515 *
516 * **Example** (Converting arguments to a tuple)
517 *
518 * ```ts import.meta.vitest
519 * import { Function } from "effect"
520 *
521 * const sumTupled = Function.tupled((x: number, y: number): number => x + y)
522 *
523 * sumTupled([1, 2]) // => 3
524 * ```
525 *
526 * @see {@link untupled} for adapting a tuple-argument function back to multiple arguments
527 *
528 * @category combinators
529 * @since 2.0.0
530 */
531export const tupled = <A extends ReadonlyArray<unknown>, B>(f: (...a: A) => B): (a: A) => B => (a) => f(...a)
532
533/**
534 * Converts a tupled function back to an uncurried function.
535 *
536 * **When to use**
537 *
538 * Use to adapt a tuple-argument function so it accepts multiple arguments.
539 *
540 * **Example** (Converting a tuple to arguments)
541 *
542 * ```ts import.meta.vitest
543 * import { Function } from "effect"
544 *
545 * const getFirst = Function.untupled(<A, B>(tuple: [A, B]): A => tuple[0])
546 *
547 * getFirst(1, 2) // => 1
548 * ```
549 *
550 * @see {@link tupled} for adapting a multi-argument function to one tuple argument
551 *
552 * @category combinators
553 * @since 2.0.0
554 */
555export const untupled = <A extends ReadonlyArray<unknown>, B>(f: (a: A) => B): (...a: A) => B => (...a) => f(a)
556
557/**
558 * Pipes the value of an expression through a left-to-right sequence of
559 * functions.
560 *
561 * **When to use**
562 *
563 * Use when you need to compose data-last functions into readable
564 * transformation pipelines instead of method-style chains.
565 *
566 * **Details**
567 *
568 * Takes an initial value, passes it to the first function, then passes each
569 * result to the next function in order. The final function result is returned.
570 *
571 * **Gotchas**
572 *
573 * Each function passed after the initial value must accept a single argument,
574 * because `pipe` calls each step with only the previous result.
575 *
576 * **Example** (Piping values through functions)
577 *
578 * In this example, `1` is passed to the first function, and each result becomes
579 * the input for the next function.
580 *
581 * ```ts import.meta.vitest
582 * import { pipe } from "effect"
583 *
584 * pipe(
585 * 1,
586 * (n) => n + 1,
587 * (n) => n * 2,
588 * (n) => `result: ${n}`
589 * ) // => "result: 4"
590 * ```
591 *
592 * **Example** (Rewriting method chains with pipe)
593 *
594 * The same transformation can be written with data-last functions.
595 *
596 * ```ts import.meta.vitest
597 * import { Array, pipe } from "effect"
598 *
599 * const numbers = [1, 2, 3, 4]
600 * const double = (n: number) => n * 2
601 * const greaterThanFour = (n: number) => n > 4
602 *
603 * pipe(
604 * numbers,
605 * Array.map(double),
606 * Array.filter(greaterThanFour)
607 * ) // => [6, 8]
608 * ```
609 *
610 * @category combinators
611 * @since 2.0.0
612 */
613export function pipe<A>(a: A): A
614export function pipe<A, B = never>(a: A, ab: (a: A) => B): B
615export function pipe<A, B = never, C = never>(
616 a: A,
617 ab: (a: A) => B,
618 bc: (b: B) => C
619): C
620export function pipe<A, B = never, C = never, D = never>(
621 a: A,
622 ab: (a: A) => B,
623 bc: (b: B) => C,
624 cd: (c: C) => D
625): D
626export function pipe<A, B = never, C = never, D = never, E = never>(
627 a: A,
628 ab: (a: A) => B,
629 bc: (b: B) => C,
630 cd: (c: C) => D,
631 de: (d: D) => E
632): E
633export function pipe<A, B = never, C = never, D = never, E = never, F = never>(
634 a: A,
635 ab: (a: A) => B,
636 bc: (b: B) => C,
637 cd: (c: C) => D,
638 de: (d: D) => E,
639 ef: (e: E) => F
640): F
641export function pipe<
642 A,
643 B = never,
644 C = never,
645 D = never,
646 E = never,
647 F = never,
648 G = never
649>(
650 a: A,
651 ab: (a: A) => B,
652 bc: (b: B) => C,
653 cd: (c: C) => D,
654 de: (d: D) => E,
655 ef: (e: E) => F,
656 fg: (f: F) => G
657): G
658export function pipe<
659 A,
660 B = never,
661 C = never,
662 D = never,
663 E = never,
664 F = never,
665 G = never,
666 H = never
667>(
668 a: A,
669 ab: (a: A) => B,
670 bc: (b: B) => C,
671 cd: (c: C) => D,
672 de: (d: D) => E,
673 ef: (e: E) => F,
674 fg: (f: F) => G,
675 gh: (g: G) => H
676): H
677export function pipe<
678 A,
679 B = never,
680 C = never,
681 D = never,
682 E = never,
683 F = never,
684 G = never,
685 H = never,
686 I = never
687>(
688 a: A,
689 ab: (a: A) => B,
690 bc: (b: B) => C,
691 cd: (c: C) => D,
692 de: (d: D) => E,
693 ef: (e: E) => F,
694 fg: (f: F) => G,
695 gh: (g: G) => H,
696 hi: (h: H) => I
697): I
698export function pipe<
699 A,
700 B = never,
701 C = never,
702 D = never,
703 E = never,
704 F = never,
705 G = never,
706 H = never,
707 I = never,
708 J = never
709>(
710 a: A,
711 ab: (a: A) => B,
712 bc: (b: B) => C,
713 cd: (c: C) => D,
714 de: (d: D) => E,
715 ef: (e: E) => F,
716 fg: (f: F) => G,
717 gh: (g: G) => H,
718 hi: (h: H) => I,
719 ij: (i: I) => J
720): J
721export function pipe<
722 A,
723 B = never,
724 C = never,
725 D = never,
726 E = never,
727 F = never,
728 G = never,
729 H = never,
730 I = never,
731 J = never,
732 K = never
733>(
734 a: A,
735 ab: (a: A) => B,
736 bc: (b: B) => C,
737 cd: (c: C) => D,
738 de: (d: D) => E,
739 ef: (e: E) => F,
740 fg: (f: F) => G,
741 gh: (g: G) => H,
742 hi: (h: H) => I,
743 ij: (i: I) => J,
744 jk: (j: J) => K
745): K
746export function pipe<
747 A,
748 B = never,
749 C = never,
750 D = never,
751 E = never,
752 F = never,
753 G = never,
754 H = never,
755 I = never,
756 J = never,
757 K = never,
758 L = never
759>(
760 a: A,
761 ab: (a: A) => B,
762 bc: (b: B) => C,
763 cd: (c: C) => D,
764 de: (d: D) => E,
765 ef: (e: E) => F,
766 fg: (f: F) => G,
767 gh: (g: G) => H,
768 hi: (h: H) => I,
769 ij: (i: I) => J,
770 jk: (j: J) => K,
771 kl: (k: K) => L
772): L
773export function pipe<
774 A,
775 B = never,
776 C = never,
777 D = never,
778 E = never,
779 F = never,
780 G = never,
781 H = never,
782 I = never,
783 J = never,
784 K = never,
785 L = never,
786 M = never
787>(
788 a: A,
789 ab: (a: A) => B,
790 bc: (b: B) => C,
791 cd: (c: C) => D,
792 de: (d: D) => E,
793 ef: (e: E) => F,
794 fg: (f: F) => G,
795 gh: (g: G) => H,
796 hi: (h: H) => I,
797 ij: (i: I) => J,
798 jk: (j: J) => K,
799 kl: (k: K) => L,
800 lm: (l: L) => M
801): M
802export function pipe<
803 A,
804 B = never,
805 C = never,
806 D = never,
807 E = never,
808 F = never,
809 G = never,
810 H = never,
811 I = never,
812 J = never,
813 K = never,
814 L = never,
815 M = never,
816 N = never
817>(
818 a: A,
819 ab: (a: A) => B,
820 bc: (b: B) => C,
821 cd: (c: C) => D,
822 de: (d: D) => E,
823 ef: (e: E) => F,
824 fg: (f: F) => G,
825 gh: (g: G) => H,
826 hi: (h: H) => I,
827 ij: (i: I) => J,
828 jk: (j: J) => K,
829 kl: (k: K) => L,
830 lm: (l: L) => M,
831 mn: (m: M) => N
832): N
833export function pipe<
834 A,
835 B = never,
836 C = never,
837 D = never,
838 E = never,
839 F = never,
840 G = never,
841 H = never,
842 I = never,
843 J = never,
844 K = never,
845 L = never,
846 M = never,
847 N = never,
848 O = never
849>(
850 a: A,
851 ab: (a: A) => B,
852 bc: (b: B) => C,
853 cd: (c: C) => D,
854 de: (d: D) => E,
855 ef: (e: E) => F,
856 fg: (f: F) => G,
857 gh: (g: G) => H,
858 hi: (h: H) => I,
859 ij: (i: I) => J,
860 jk: (j: J) => K,
861 kl: (k: K) => L,
862 lm: (l: L) => M,
863 mn: (m: M) => N,
864 no: (n: N) => O
865): O
866export function pipe<
867 A,
868 B = never,
869 C = never,
870 D = never,
871 E = never,
872 F = never,
873 G = never,
874 H = never,
875 I = never,
876 J = never,
877 K = never,
878 L = never,
879 M = never,
880 N = never,
881 O = never,
882 P = never
883>(
884 a: A,
885 ab: (a: A) => B,
886 bc: (b: B) => C,
887 cd: (c: C) => D,
888 de: (d: D) => E,
889 ef: (e: E) => F,
890 fg: (f: F) => G,
891 gh: (g: G) => H,
892 hi: (h: H) => I,
893 ij: (i: I) => J,
894 jk: (j: J) => K,
895 kl: (k: K) => L,
896 lm: (l: L) => M,
897 mn: (m: M) => N,
898 no: (n: N) => O,
899 op: (o: O) => P
900): P
901export function pipe<
902 A,
903 B = never,
904 C = never,
905 D = never,
906 E = never,
907 F = never,
908 G = never,
909 H = never,
910 I = never,
911 J = never,
912 K = never,
913 L = never,
914 M = never,
915 N = never,
916 O = never,
917 P = never,
918 Q = never
919>(
920 a: A,
921 ab: (a: A) => B,
922 bc: (b: B) => C,
923 cd: (c: C) => D,
924 de: (d: D) => E,
925 ef: (e: E) => F,
926 fg: (f: F) => G,
927 gh: (g: G) => H,
928 hi: (h: H) => I,
929 ij: (i: I) => J,
930 jk: (j: J) => K,
931 kl: (k: K) => L,
932 lm: (l: L) => M,
933 mn: (m: M) => N,
934 no: (n: N) => O,
935 op: (o: O) => P,
936 pq: (p: P) => Q
937): Q
938export function pipe<
939 A,
940 B = never,
941 C = never,
942 D = never,
943 E = never,
944 F = never,
945 G = never,
946 H = never,
947 I = never,
948 J = never,
949 K = never,
950 L = never,
951 M = never,
952 N = never,
953 O = never,
954 P = never,
955 Q = never,
956 R = never
957>(
958 a: A,
959 ab: (a: A) => B,
960 bc: (b: B) => C,
961 cd: (c: C) => D,
962 de: (d: D) => E,
963 ef: (e: E) => F,
964 fg: (f: F) => G,
965 gh: (g: G) => H,
966 hi: (h: H) => I,
967 ij: (i: I) => J,
968 jk: (j: J) => K,
969 kl: (k: K) => L,
970 lm: (l: L) => M,
971 mn: (m: M) => N,
972 no: (n: N) => O,
973 op: (o: O) => P,
974 pq: (p: P) => Q,
975 qr: (q: Q) => R
976): R
977export function pipe<
978 A,
979 B = never,
980 C = never,
981 D = never,
982 E = never,
983 F = never,
984 G = never,
985 H = never,
986 I = never,
987 J = never,
988 K = never,
989 L = never,
990 M = never,
991 N = never,
992 O = never,
993 P = never,
994 Q = never,
995 R = never,
996 S = never
997>(
998 a: A,
999 ab: (a: A) => B,
1000 bc: (b: B) => C,
1001 cd: (c: C) => D,
1002 de: (d: D) => E,
1003 ef: (e: E) => F,
1004 fg: (f: F) => G,
1005 gh: (g: G) => H,
1006 hi: (h: H) => I,
1007 ij: (i: I) => J,
1008 jk: (j: J) => K,
1009 kl: (k: K) => L,
1010 lm: (l: L) => M,
1011 mn: (m: M) => N,
1012 no: (n: N) => O,
1013 op: (o: O) => P,
1014 pq: (p: P) => Q,
1015 qr: (q: Q) => R,
1016 rs: (r: R) => S
1017): S
1018export function pipe<
1019 A,
1020 B = never,
1021 C = never,
1022 D = never,
1023 E = never,
1024 F = never,
1025 G = never,
1026 H = never,
1027 I = never,
1028 J = never,
1029 K = never,
1030 L = never,
1031 M = never,
1032 N = never,
1033 O = never,
1034 P = never,
1035 Q = never,
1036 R = never,
1037 S = never,
1038 T = never
1039>(
1040 a: A,
1041 ab: (a: A) => B,
1042 bc: (b: B) => C,
1043 cd: (c: C) => D,
1044 de: (d: D) => E,
1045 ef: (e: E) => F,
1046 fg: (f: F) => G,
1047 gh: (g: G) => H,
1048 hi: (h: H) => I,
1049 ij: (i: I) => J,
1050 jk: (j: J) => K,
1051 kl: (k: K) => L,
1052 lm: (l: L) => M,
1053 mn: (m: M) => N,
1054 no: (n: N) => O,
1055 op: (o: O) => P,
1056 pq: (p: P) => Q,
1057 qr: (q: Q) => R,
1058 rs: (r: R) => S,
1059 st: (s: S) => T
1060): T
1061export function pipe(a: unknown, ...args: Array<any>): unknown {
1062 return pipeArguments(a, args as any)
1063}
1064
1065/**
1066 * Performs left-to-right function composition.
1067 *
1068 * **When to use**
1069 *
1070 * Use to build a reusable function from a left-to-right sequence of
1071 * transformations.
1072 *
1073 * **Details**
1074 *
1075 * The first function may have any arity. Every following function must be
1076 * unary.
1077 *
1078 * **Example** (Composing functions left to right)
1079 *
1080 * ```ts import.meta.vitest
1081 * import { flow } from "effect"
1082 *
1083 * const len = (s: string): number => s.length
1084 * const double = (n: number): number => n * 2
1085 *
1086 * const f = flow(len, double)
1087 *
1088 * f("aaa") // => 6
1089 * ```
1090 *
1091 * @see {@link pipe} for applying a value through a left-to-right sequence immediately
1092 * @see {@link compose} for composing exactly two functions
1093 *
1094 * @category combinators
1095 * @since 2.0.0
1096 */
1097export function flow<A extends ReadonlyArray<unknown>, B = never>(
1098 ab: (...a: A) => B
1099): (...a: A) => B
1100export function flow<A extends ReadonlyArray<unknown>, B = never, C = never>(
1101 ab: (...a: A) => B,
1102 bc: (b: B) => C
1103): (...a: A) => C
1104export function flow<
1105 A extends ReadonlyArray<unknown>,
1106 B = never,
1107 C = never,
1108 D = never
1109>(ab: (...a: A) => B, bc: (b: B) => C, cd: (c: C) => D): (...a: A) => D
1110export function flow<
1111 A extends ReadonlyArray<unknown>,
1112 B = never,
1113 C = never,
1114 D = never,
1115 E = never
1116>(
1117 ab: (...a: A) => B,
1118 bc: (b: B) => C,
1119 cd: (c: C) => D,
1120 de: (d: D) => E
1121): (...a: A) => E
1122export function flow<
1123 A extends ReadonlyArray<unknown>,
1124 B = never,
1125 C = never,
1126 D = never,
1127 E = never,
1128 F = never
1129>(
1130 ab: (...a: A) => B,
1131 bc: (b: B) => C,
1132 cd: (c: C) => D,
1133 de: (d: D) => E,
1134 ef: (e: E) => F
1135): (...a: A) => F
1136export function flow<
1137 A extends ReadonlyArray<unknown>,
1138 B = never,
1139 C = never,
1140 D = never,
1141 E = never,
1142 F = never,
1143 G = never
1144>(
1145 ab: (...a: A) => B,
1146 bc: (b: B) => C,
1147 cd: (c: C) => D,
1148 de: (d: D) => E,
1149 ef: (e: E) => F,
1150 fg: (f: F) => G
1151): (...a: A) => G
1152export function flow<
1153 A extends ReadonlyArray<unknown>,
1154 B = never,
1155 C = never,
1156 D = never,
1157 E = never,
1158 F = never,
1159 G = never,
1160 H = never
1161>(
1162 ab: (...a: A) => B,
1163 bc: (b: B) => C,
1164 cd: (c: C) => D,
1165 de: (d: D) => E,
1166 ef: (e: E) => F,
1167 fg: (f: F) => G,
1168 gh: (g: G) => H
1169): (...a: A) => H
1170export function flow<
1171 A extends ReadonlyArray<unknown>,
1172 B = never,
1173 C = never,
1174 D = never,
1175 E = never,
1176 F = never,
1177 G = never,
1178 H = never,
1179 I = never
1180>(
1181 ab: (...a: A) => B,
1182 bc: (b: B) => C,
1183 cd: (c: C) => D,
1184 de: (d: D) => E,
1185 ef: (e: E) => F,
1186 fg: (f: F) => G,
1187 gh: (g: G) => H,
1188 hi: (h: H) => I
1189): (...a: A) => I
1190export function flow<
1191 A extends ReadonlyArray<unknown>,
1192 B = never,
1193 C = never,
1194 D = never,
1195 E = never,
1196 F = never,
1197 G = never,
1198 H = never,
1199 I = never,
1200 J = never
1201>(
1202 ab: (...a: A) => B,
1203 bc: (b: B) => C,
1204 cd: (c: C) => D,
1205 de: (d: D) => E,
1206 ef: (e: E) => F,
1207 fg: (f: F) => G,
1208 gh: (g: G) => H,
1209 hi: (h: H) => I,
1210 ij: (i: I) => J
1211): (...a: A) => J
1212export function flow(
1213 ab: Function,
1214 bc?: Function,
1215 cd?: Function,
1216 de?: Function,
1217 ef?: Function,
1218 fg?: Function,
1219 gh?: Function,
1220 hi?: Function,
1221 ij?: Function
1222): unknown {
1223 switch (arguments.length) {
1224 case 1:
1225 return ab
1226 case 2:
1227 return function(this: unknown) {
1228 return bc!(ab.apply(this, arguments))
1229 }
1230 case 3:
1231 return function(this: unknown) {
1232 return cd!(bc!(ab.apply(this, arguments)))
1233 }
1234 case 4:
1235 return function(this: unknown) {
1236 return de!(cd!(bc!(ab.apply(this, arguments))))
1237 }
1238 case 5:
1239 return function(this: unknown) {
1240 return ef!(de!(cd!(bc!(ab.apply(this, arguments)))))
1241 }
1242 case 6:
1243 return function(this: unknown) {
1244 return fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments))))))
1245 }
1246 case 7:
1247 return function(this: unknown) {
1248 return gh!(fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments)))))))
1249 }
1250 case 8:
1251 return function(this: unknown) {
1252 return hi!(gh!(fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments))))))))
1253 }
1254 case 9:
1255 return function(this: unknown) {
1256 return ij!(hi!(gh!(fg!(ef!(de!(cd!(bc!(ab.apply(this, arguments)))))))))
1257 }
1258 }
1259 return
1260}
1261
1262/**
1263 * Creates a compile-time placeholder for a value of any type.
1264 *
1265 * **When to use**
1266 *
1267 * Use as a temporary typed placeholder while developing incomplete code.
1268 *
1269 * **Gotchas**
1270 *
1271 * `hole` is intended for temporary development use. If the placeholder is
1272 * evaluated at runtime, it throws.
1273 *
1274 * **Example** (Creating a development placeholder)
1275 *
1276 * ```ts import.meta.vitest
1277 * import { hole } from "effect"
1278 *
1279 * // Intentionally not called: `hole` throws if the placeholder is evaluated.
1280 * const buildUser = (id: number): { readonly id: number; readonly name: string } => ({
1281 * id,
1282 * name: hole<string>()
1283 * })
1284 *
1285 * ```
1286 *
1287 * @category utility types
1288 * @since 2.0.0
1289 */
1290export const hole: <T>() => T = cast(absurd)
1291
1292/**
1293 * Returns the second argument and discards the first. The SK combinator is
1294 * a fundamental combinator in the lambda calculus and the SKI combinator
1295 * calculus.
1296 *
1297 * **When to use**
1298 *
1299 * Use to discard the first argument and return the second argument.
1300 *
1301 * **Example** (Discarding the first argument)
1302 *
1303 * ```ts import.meta.vitest
1304 * import { Function } from "effect"
1305 *
1306 * Function.SK(0, "hello") // => "hello"
1307 * ```
1308 *
1309 * @category combinators
1310 * @since 2.0.0
1311 */
1312export const SK = <A, B>(_: A, b: B): B => b
1313
1314/**
1315 * Creates a memoized function whose input is an object, caching results by
1316 * object identity.
1317 *
1318 * **When to use**
1319 *
1320 * Use to reuse the result of a synchronous computation whose output is stable
1321 * for a given object reference.
1322 *
1323 * **Details**
1324 *
1325 * Each memoized wrapper owns a private `WeakMap` keyed by object identity.
1326 *
1327 * **Gotchas**
1328 *
1329 * `undefined` is reserved to represent a cache miss and is therefore not
1330 * supported as a return value.
1331 *
1332 * Structurally equal objects do not share cache entries. If the same object is
1333 * mutated after its first call, later calls still return the cached result for
1334 * that reference.
1335 *
1336 * @category caching
1337 * @since 4.0.0
1338 */
1339export function memoize<A extends object, O extends {} | null>(f: (a: A) => O): (ast: A) => O {
1340 const cache = new WeakMap<object, O>()
1341 return (a) => {
1342 const cached = cache.get(a)
1343 if (cached !== undefined) return cached
1344 const result = f(a)
1345 cache.set(a, result)
1346 return result
1347 }
1348}
1349
1350/**
1351 * Creates a memoized idempotent object transformation that caches both inputs
1352 * and their outputs by object identity.
1353 *
1354 * **When to use**
1355 *
1356 * Use when an object transformation is idempotent and its output can be safely
1357 * reused as a fixed point.
1358 *
1359 * **Details**
1360 *
1361 * After computing an input, the returned function caches both the input and
1362 * the output. Calling it with either reference returns the output without
1363 * invoking the supplied function again.
1364 *
1365 * **Gotchas**
1366 *
1367 * The returned function treats each computed output as a fixed point. If
1368 * applying the supplied function to an output would produce an observably
1369 * different value, this memoization changes that behavior.
1370 *
1371 * @see {@link memoize} for memoizing functions without an idempotence requirement
1372 * @category caching
1373 * @since 4.0.0
1374 */
1375export function memoizeIdempotent<A extends object>(f: (a: A) => A): (a: A) => A {
1376 const cache = new WeakMap<A, A>()
1377 return (a) => {
1378 const cached = cache.get(a)
1379 if (cached !== undefined) return cached
1380 const result = f(a)
1381 cache.set(a, result)
1382 if (result !== a) {
1383 cache.set(result, result)
1384 }
1385 return result
1386 }
1387}