EdgeAIG's picture
download
raw
15.9 kB
/**
* Works with fixed-length arrays, also called tuples.
*
* The runtime helpers in this module create new tuples instead of mutating
* their inputs, and the types preserve element positions where possible. The
* helpers cover tuple construction, indexed access, selecting or removing
* positions, appending values, transforming elements, renaming indices, mapping
* typed positions, and deriving comparison or combination helpers for tuple
* shapes.
*
* @since 2.0.0
*/
import * as Combiner from "./Combiner.js";
import * as Equivalence from "./Equivalence.js";
import { dual } from "./Function.js";
import * as order from "./Order.js";
import * as Reducer from "./Reducer.js";
/**
* Creates a tuple from the provided arguments.
*
* **When to use**
*
* Use when you need a properly typed tuple without writing `[a, b, c] as const`
* or another manual cast.
*
* **Details**
*
* The returned value has the exact tuple type, with each element's literal type
* preserved.
*
* **Example** (Creating a tuple)
*
* ```ts
* import { Tuple } from "effect"
*
* const point = Tuple.make(10, 20, "red")
* console.log(point) // [10, 20, "red"]
* ```
*
* @see {@link get} – access a single element by index
* @see {@link appendElement} – append an element to a tuple
* @category constructors
* @since 2.0.0
*/
export const make = (...elements) => elements;
/**
* Retrieves the element at the specified index from a tuple.
*
* **When to use**
*
* Use when a single tuple element should be extracted in a pipeline.
*
* **Details**
*
* The index is constrained to valid tuple positions at the type level.
*
* **Example** (Extracting an element by index)
*
* ```ts
* import { pipe, Tuple } from "effect"
*
* const last = pipe(Tuple.make(1, true, "hello"), Tuple.get(2))
* console.log(last) // "hello"
* ```
*
* @see {@link make} – create a tuple
* @see {@link pick} – extract multiple elements into a new tuple
* @category getters
* @since 4.0.0
*/
export const get = /*#__PURE__*/dual(2, (self, index) => self[index]);
/**
* Creates a new tuple containing only the elements at the specified indices.
*
* **When to use**
*
* Use to select a subset of elements from a tuple by position.
*
* **Details**
*
* The result order matches the order of the provided indices.
*
* **Example** (Selecting elements by index)
*
* ```ts
* import { Tuple } from "effect"
*
* const result = Tuple.pick(["a", "b", "c", "d"], [0, 2, 3])
* console.log(result) // ["a", "c", "d"]
* ```
*
* @see {@link omit} – the inverse (exclude indices instead)
* @see {@link get} – extract a single element
* @category filtering
* @since 4.0.0
*/
export const pick = /*#__PURE__*/dual(2, (self, indices) => {
return indices.map(i => self[i]);
});
/**
* Creates a new tuple with the elements at the specified indices removed.
*
* **When to use**
*
* Use to drop elements from a tuple by position.
*
* **Details**
*
* Elements not at the specified indices are kept in their original order.
*
* **Example** (Removing elements by index)
*
* ```ts
* import { Tuple } from "effect"
*
* const result = Tuple.omit(["a", "b", "c", "d"], [1, 3])
* console.log(result) // ["a", "c"]
* ```
*
* @see {@link pick} – the inverse (keep only specified indices)
* @category filtering
* @since 4.0.0
*/
export const omit = /*#__PURE__*/dual(2, (self, indices) => {
const toDrop = new Set(indices);
return self.filter((_, i) => !toDrop.has(i));
});
/**
* Appends a single element to the end of a tuple.
*
* **When to use**
*
* Use when you need the appended value to remain part of the tuple's type-level
* shape and preserve literal element positions.
*
* **Details**
*
* The result type is `[...T, E]`, preserving all existing element types.
*
* **Example** (Appending an element)
*
* ```ts
* import { pipe, Tuple } from "effect"
*
* const result = pipe(Tuple.make(1, 2), Tuple.appendElement("end"))
* console.log(result) // [1, 2, "end"]
* ```
*
* @see {@link appendElements} – append multiple elements (another tuple)
* @category combining
* @since 2.0.0
*/
export const appendElement = /*#__PURE__*/dual(2, (self, element) => [...self, element]);
/**
* Concatenates two tuples into a single tuple.
*
* **When to use**
*
* Use to append all elements from one tuple to another tuple.
*
* **Details**
*
* The result type is `[...T1, ...T2]`, preserving all element types from both
* tuples. Neither input tuple is mutated; a fresh tuple is returned.
*
* **Example** (Concatenating tuples)
*
* ```ts
* import { pipe, Tuple } from "effect"
*
* const result = pipe(Tuple.make(1, 2), Tuple.appendElements(["a", "b"] as const))
* console.log(result) // [1, 2, "a", "b"]
* ```
*
* @see {@link appendElement} – append a single element
* @category combining
* @since 4.0.0
*/
export const appendElements = /*#__PURE__*/dual(2, (self, that) => [...self, ...that]);
/**
* Transforms elements of a tuple by providing an array of transform functions.
* Each function applies to the element at the same position. Positions beyond
* the array's length are copied unchanged.
*
* **When to use**
*
* Use when you want to update the first N elements while keeping the rest.
*
* **Details**
*
* Each transform function receives the current value and can return a different
* type.
*
* **Example** (Transforming selected elements)
*
* ```ts
* import { pipe, Tuple } from "effect"
*
* const result = pipe(
* Tuple.make("hello", 42, true),
* Tuple.evolve([
* (s) => s.toUpperCase(),
* (n) => n * 2
* ])
* )
* console.log(result) // ["HELLO", 84, true]
* ```
*
* @see {@link map} – apply the same transformation to all elements
* @see {@link renameIndices} – swap element positions
* @category mapping
* @since 4.0.0
*/
export const evolve = /*#__PURE__*/dual(2, (self, evolver) => {
return self.map((e, i) => evolver[i] !== undefined ? evolver[i](e) : e);
});
/**
* Renames tuple indices by providing an array of stringified source
* indices. Each position in the array specifies which index to read from
* (e.g., `["2", "1", "0"]` reverses a 3-element tuple).
*
* **When to use**
*
* Use to reorder tuple elements while preserving index-specific types.
*
* **Details**
*
* The mapping returns a tuple in the requested index order.
*
* **Gotchas**
*
* The mapping uses stringified source indices, not arbitrary names.
*
* **Example** (Swapping elements)
*
* ```ts
* import { pipe, Tuple } from "effect"
*
* const result = pipe(
* Tuple.make("a", "b", "c"),
* Tuple.renameIndices(["2", "1", "0"])
* )
* console.log(result) // ["c", "b", "a"]
* ```
*
* @see {@link evolve} – transform element values instead of positions
* @category Index utilities
* @since 4.0.0
*/
export const renameIndices = /*#__PURE__*/dual(2, (self, mapping) => {
return self.map((e, i) => mapping[i] !== undefined ? self[mapping[i]] : e);
});
/**
* Applies a `Struct.Lambda` transformation to every element in a tuple.
*
* **When to use**
*
* Use when you want to apply the same transformation to every tuple element.
*
* **Details**
*
* The lambda lets the compiler track the output type for each element.
*
* **Gotchas**
*
* The lambda must be created with `Struct.lambda`; a plain function will not
* type-check.
*
* **Example** (Wrapping every element in an array)
*
* ```ts
* import { pipe, Struct, Tuple } from "effect"
*
* interface AsArray extends Struct.Lambda {
* <A>(self: A): Array<A>
* readonly "~lambda.out": Array<this["~lambda.in"]>
* }
*
* const asArray = Struct.lambda<AsArray>((a) => [a])
* const result = pipe(Tuple.make(1, "hello", true), Tuple.map(asArray))
* console.log(result) // [[1], ["hello"], [true]]
* ```
*
* @see {@link mapPick} – apply a lambda only to selected indices
* @see {@link mapOmit} – apply a lambda to all indices except selected ones
* @see {@link evolve} – apply different functions to different indices
* @category mapping
* @since 3.9.0
*/
export const map = /*#__PURE__*/dual(2, (self, lambda) => {
return self.map(e => lambda(e));
});
/**
* Applies a `Struct.Lambda` transformation only to the elements at the
* specified indices; all other elements are copied unchanged.
*
* **When to use**
*
* Use when you want to apply the same transformation to a subset of
* positions.
*
* **Example** (Wrapping only selected elements in arrays)
*
* ```ts
* import { pipe, Struct, Tuple } from "effect"
*
* interface AsArray extends Struct.Lambda {
* <A>(self: A): Array<A>
* readonly "~lambda.out": Array<this["~lambda.in"]>
* }
*
* const asArray = Struct.lambda<AsArray>((a) => [a])
* const result = pipe(
* Tuple.make(1, "hello", true),
* Tuple.mapPick([0, 2], asArray)
* )
* console.log(result) // [[1], "hello", [true]]
* ```
*
* @see {@link map} – apply a lambda to all elements
* @see {@link mapOmit} – apply a lambda to all elements except selected ones
* @category mapping
* @since 4.0.0
*/
export const mapPick = /*#__PURE__*/dual(3, (self, indices, lambda) => {
const toPick = new Set(indices);
return self.map((e, i) => toPick.has(i) ? lambda(e) : e);
});
/**
* Applies a `Struct.Lambda` transformation to all elements except those at the
* specified indices; the excluded elements are copied unchanged.
*
* **When to use**
*
* Use when most elements should be transformed but a few should be
* preserved.
*
* **Example** (Wrapping all elements except one in arrays)
*
* ```ts
* import { pipe, Struct, Tuple } from "effect"
*
* interface AsArray extends Struct.Lambda {
* <A>(self: A): Array<A>
* readonly "~lambda.out": Array<this["~lambda.in"]>
* }
*
* const asArray = Struct.lambda<AsArray>((a) => [a])
* const result = pipe(
* Tuple.make(1, "hello", true),
* Tuple.mapOmit([1], asArray)
* )
* console.log(result) // [[1], "hello", [true]]
* ```
*
* @see {@link map} – apply a lambda to all elements
* @see {@link mapPick} – apply a lambda only to selected indices
* @category mapping
* @since 4.0.0
*/
export const mapOmit = /*#__PURE__*/dual(3, (self, indices, lambda) => {
const toOmit = new Set(indices);
return self.map((e, i) => toOmit.has(i) ? e : lambda(e));
});
/**
* Creates an `Equivalence` for tuples by comparing corresponding elements
* using the provided per-position `Equivalence`s. Two tuples are equivalent
* when all their corresponding elements are equivalent.
*
* **When to use**
*
* Use when you need an `Equivalence` to compare tuples element-by-element.
*
* **Details**
*
* This is an alias of `Equivalence.Tuple`.
*
* **Example** (Comparing tuples for equivalence)
*
* ```ts
* import { Equivalence, Tuple } from "effect"
*
* const eq = Tuple.makeEquivalence([
* Equivalence.strictEqual<string>(),
* Equivalence.strictEqual<number>()
* ])
*
* console.log(eq(["Alice", 30], ["Alice", 30])) // true
* console.log(eq(["Alice", 30], ["Bob", 30])) // false
* ```
*
* @see {@link makeOrder} – create an `Order` for tuples
* @category instances
* @since 4.0.0
*/
export const makeEquivalence = Equivalence.Tuple;
/**
* Creates an `Order` for tuples by comparing corresponding elements using the
* provided per-position `Order`s. Elements are compared left-to-right; the
* first non-zero comparison determines the result.
*
* **When to use**
*
* Use when you need to sort fixed-position arrays lexicographically, with each
* position using its own ordering rule.
*
* **Details**
*
* This is an alias of `Order.Tuple`.
*
* **Example** (Ordering tuples)
*
* ```ts
* import { Number, String, Tuple } from "effect"
*
* const ord = Tuple.makeOrder([String.Order, Number.Order])
*
* console.log(ord(["Alice", 30], ["Bob", 25])) // -1
* console.log(ord(["Alice", 30], ["Alice", 30])) // 0
* ```
*
* @see {@link makeEquivalence} – create an `Equivalence` for tuples
* @category ordering
* @since 4.0.0
*/
export const makeOrder = order.Tuple;
export {
/**
* Checks whether an array has exactly `N` elements, narrowing the type to a
* fixed-length tuple.
*
* **When to use**
*
* Use to guard that an array has exactly the tuple length expected at
* runtime.
*
* **Details**
*
* This is a re-export of `Predicate.isTupleOf`. It narrows the type to
* `TupleOf<N, T>` in the truthy branch.
*
* **Gotchas**
*
* This only checks `.length`; it does not validate element types.
*
* **Example** (Checking exact length)
*
* ```ts
* import { Tuple } from "effect"
*
* const arr: Array<number> = [1, 2, 3]
* if (Tuple.isTupleOf(arr, 3)) {
* console.log(arr)
* // ^? [number, number, number]
* }
* ```
*
* @see `isTupleOfAtLeast` – check for a minimum length
* @category guards
* @since 3.3.0
*/
isTupleOf,
/**
* Checks whether an array has at least `N` elements, narrowing the type to a
* tuple with a minimum length.
*
* **When to use**
*
* Use to guard that an array has at least the tuple length expected at
* runtime.
*
* **Details**
*
* This is a re-export of `Predicate.isTupleOfAtLeast`. It narrows the type to
* `TupleOfAtLeast<N, T>` in the truthy branch.
*
* **Gotchas**
*
* This only checks `.length`; it does not validate element types.
*
* **Example** (Checking minimum length)
*
* ```ts
* import { Tuple } from "effect"
*
* const arr: Array<number> = [1, 2, 3, 4]
* if (Tuple.isTupleOfAtLeast(arr, 3)) {
* console.log(arr)
* // ^? [number, number, number, ...number[]]
* }
* ```
*
* @see `isTupleOf` – check for an exact length
* @category guards
* @since 3.3.0
*/
isTupleOfAtLeast } from "./Predicate.js";
/**
* Creates a `Combiner` for a tuple shape by providing a `Combiner` for each
* position. When two tuples are combined, each element is merged using its
* corresponding combiner.
*
* **When to use**
*
* Use when you need to merge two same-shape tuples by combining each position
* independently, such as summing counters or concatenating strings.
*
* **Example** (Combining tuple elements)
*
* ```ts
* import { Number, String, Tuple } from "effect"
*
* const C = Tuple.makeCombiner<readonly [number, string]>([
* Number.ReducerSum,
* String.ReducerConcat
* ])
*
* const result = C.combine([1, "hello"], [2, " world"])
* console.log(result) // [3, "hello world"]
* ```
*
* @see {@link makeReducer} – like `makeCombiner` but with an initial value
* @category combining
* @since 4.0.0
*/
export function makeCombiner(combiners) {
return Combiner.make((self, that) => {
const out = [];
for (let i = 0; i < self.length; i++) {
out.push(combiners[i].combine(self[i], that[i]));
}
return out;
});
}
/**
* Creates a `Reducer` for a tuple shape by providing a `Reducer` for each
* position. The initial value is derived from each position's
* `Reducer.initialValue`. When reducing a collection of tuples, each element
* is combined independently.
*
* **When to use**
*
* Use when you need to fold same-shape tuples by accumulating each position
* independently into one summary tuple.
*
* **Example** (Reducing a collection of tuples)
*
* ```ts
* import { Number, String, Tuple } from "effect"
*
* const R = Tuple.makeReducer<readonly [number, string]>([
* Number.ReducerSum,
* String.ReducerConcat
* ])
*
* const result = R.combineAll([
* [1, "a"],
* [2, "b"],
* [3, "c"]
* ])
* console.log(result) // [6, "abc"]
* ```
*
* @see {@link makeCombiner} – like `makeReducer` but without an initial value
* @category folding
* @since 4.0.0
*/
export function makeReducer(reducers) {
const combine = makeCombiner(reducers).combine;
const initialValue = [];
for (let i = 0; i < reducers.length; i++) {
initialValue.push(reducers[i].initialValue);
}
return Reducer.make(combine, initialValue);
}
//# sourceMappingURL=Tuple.js.map

Xet Storage Details

Size:
15.9 kB
·
Xet hash:
26b75b8f5cd3d0a9502a33266512a928de05addae8b7ebe0131eb0316b3aa096

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.