/** * Optics are a collection of combinators for focusing on specific parts of data * within an existing structure. The core operations are view, review, and * modify. Optics in the fun library are based on the concept of Kliesli optics * as outlined * [here](https://gist.github.com/serras/5152ec18ec5223b676cc67cac0e99b70). * * Their uses include (but are not limited to): * * Accessing deeply nested data * * Mapping related but distinct types without loss of fidelity * * Immutably modifying large data structures * * At its core, instead of separating the view method into view, preview, and * toList of, as is done in many languages and libraries. This implementation * uses a single view method that operates as a Kliesli arrow (a -> mb) where * the m in this case is limited to the Identity, Option, and Array monads, * which can be composed using Natural transformations and flatMap. * * In addition to view, there are also implementations of review and modify, * which also have composition functions.. but the research for composition is * not yet complete for review. * * In any case, this implementation of optics is distinct from Laarhoven lenses * and profunctor optics, and is much more compact and performant in typescript * than those implementations. * * @module Optic * @since 2.0.0 */ import "./_dnt.polyfills.js"; import type { $, Kind } from "./kind.js"; import type { Comparable } from "./comparable.js"; import type { Initializable } from "./initializable.js"; import type { Either } from "./either.js"; import type { Option } from "./option.js"; import type { Pair } from "./pair.js"; import type { Predicate } from "./predicate.js"; import type { ReadonlyRecord } from "./record.js"; import type { Refinement } from "./refinement.js"; import type { Traversable } from "./traversable.js"; import type { Tree } from "./tree.js"; import * as I from "./identity.js"; import * as O from "./option.js"; import * as A from "./array.js"; /** * A runtime tag and type that indicates an Optic has a view function of the form * `(s: S) => Identity`. */ export declare const LensTag: "Lens"; export type LensTag = typeof LensTag; /** * A runtime tag and type that indicates an Optic has a view function of the form * `(s: S) => Option`. */ export declare const AffineTag: "Affine"; export type AffineTag = typeof AffineTag; /** * A runtime tag and type that indicates an Optic has a view function of the form * `(s: S) => ReadonlyArray`. */ export declare const FoldTag: "Fold"; export type FoldTag = typeof FoldTag; /** * A type union of the supported view tags for a Viewer */ export type Tag = LensTag | AffineTag | FoldTag; /** * A type level mapping from an Optic Tag to its associated output Kind. This is * used to substitute the container of the output of a view function. */ type ToKind = T extends LensTag ? I.KindIdentity : T extends AffineTag ? O.KindOption : T extends FoldTag ? A.KindArray : never; /** * A type level computation of Optic Tags. When composing the view functions of * two optics their output types must be aligned. This type aligns their tags at * the type level. It has a corresponding runtime align function. */ type Align = U extends FoldTag ? FoldTag : V extends FoldTag ? FoldTag : U extends AffineTag ? AffineTag : V extends AffineTag ? AffineTag : LensTag; /** * Given a Viewer and an optic tag V, this function produces a view * function that can be used in a Viewer. However, not all casts are valid. * The following are the only supported casts, by their optic tag: * * * LensTag => LensTag * * LensTag => AffineTag * * LensTag => FoldTag * * AffineTag => AffineTag * * AffineTag => FoldTag * * FoldTag => FoldTag * * The following are unsupported casts which will throw at runtime: * * * AffineTag => LensTag * * FoldTag => AffineTag * * FoldTag => LensTag * * This library has no code that leads to unsupported casts, but if one wishes * to extend its functionality by replicating the cast logic, these cases must * be considered. */ export declare function _unsafeCast(viewer: Viewer, tag: V): Viewer["view"]; /** * A Viewer implements a view function `(s: S) => T`. This is * effectively a Kliesli Arrow. The valid types of T are Identity, Option, and * Array. Viewer also includes a runtime tag corresponding to the return type of * the view function to aid in composition. * * @since 2.0.0 */ export interface Viewer { readonly tag: T; readonly view: (s: S) => $, [A, never, never]>; } /** * The Modifier type implements the modify function * `(mod: (a: A) => A) => (s: S) => S`. This type is directly composable and * from it one can recover set/replace behavior. * * @since 2.0.0 */ export interface Modifier { readonly modify: (modifyFn: (a: A) => A) => (s: S) => S; } /** * The Reviewer S`. This * type is directly composable and is used when the S type in Viewer * can be reconstructed from A. Some examples are constructing `Option` * from `number`, `Array` from `number`, etc. * * @since 2.0.0 */ export interface Reviewer { readonly review: (a: A) => S; } /** * An Optic is defined as a Viewer combined with a Modifier. This is the root type for the specific types of Optics defined below. * * @since 2.0.0 */ export interface Optic extends Viewer, Modifier { } /** * Lens is an alias of Optic. This means that the view * function of a Lens returns a pure A value. `(s: S) => A`. Some example lenses * are accessing the property of a struct, accessing the first value in a Pair, * and the trivial identity Lens. In general, a Lens is used for focusing on * *exactly one* value `A` contained in the value `S`. * * @since 2.0.0 */ export type Lens = Optic; /** * Iso is an alias of Lens & Reviewer. This means that an Iso * operates exactly like a Lens with the added ability to go back from A to S. * * @since 2.0.0 */ export type Iso = Lens & Reviewer; /** * AffineFold is an alias of Optic. This means the view * function of an AffineFold returns an Option, `(s: S) => Option`. Some * example AffineFolds are accessing a value at an index in an array, accessing * the value in an Option, and accessing a key in a Record type. In general, * an AffineFold is used for focusing on *zero or one* value `A` contained in * the value `S`. * * @since 2.0.0 */ export type AffineFold = Optic; /** * Prism is an alias of AffineFold & Reviewer. This means that * a Prism operates exactly like an AffineFold with the added ability to * *reconstruct* an S from an A. Examples of this are reconstructing an * Option from a number, or reconstructing Either from a * string or a number. * * @since 2.0.0 */ export type Prism = AffineFold & Reviewer; /** * Fold is an alias of Optic. This means that the view * function of a Fold returns a ReadonlyArray, `(s: S) => ReadonlyArray`. * Some example Folds are accessing all of the values in a Record, Tree, Set, * etc. In general, a Fold is used for focusing on *any number* of values `A` * contained in the value `S`. * * @since 2.0.0 */ export type Fold = Optic; /** * Refold is an alias of Fold & Reviewer. This means that a * Refold operates exactly like a Fold with the added ability to *reconstruct* * an S from a single value A. Examples of this are reconstructing an Array * from a value A, or reconstructing a Tree from a value A. * * @since 2.0.0 */ export type Refold = Fold & Reviewer; /** * Construct a Viewer from a tag T and a view function that matches * said tag. This is a raw constructor and is generally only useful if there is * a case where a structure can be lensed into but not reconstructed or * traversed. However, this is the core composable structure of optics, as they * are primarily meant as a way to retrieve data from an existing structure. * * @example The "Lens" viewer retrieves a single value that always exists. * ```ts * import type { Pair } from "./pair.ts"; * * import * as O from "./optic.ts"; * import * as P from "./pair.ts"; * * const fst = () => O.viewer, A>( * O.LensTag, * P.getFirst, * ); * * const numPair = fst(); * * const result1 = numPair.view(P.pair(1, 2)); // 1 * const result2 = numPair.view(P.pair(2, 1)); // 2 * ``` * * @example The "Affine" viewer retrieves a single value that might exists. * ```ts * import type { Either } from "./either.ts"; * * import * as O from "./optic.ts"; * import * as E from "./either.ts"; * * const right = () => O.viewer, R>( * O.AffineTag, * E.getRight, * ); * * const numberEither = right(); * * const result1 = numberEither.view(E.right(1)); // Some(1) * const result2 = numberEither.view(E.left("Hello")); // None * ``` * * @example The "Fold" viewer retrieves zero or more values as an Array. * ```ts * import * as O from "./optic.ts"; * * const record = () => O.viewer, A>( * O.FoldTag, * Object.values, * ); * * const numberRecord = record(); * * const result = numberRecord.view({ * "one": 1, * "two": 2, * }); // [1, 2] * ``` * * @since 2.0.0 */ export declare function viewer(tag: T, view: (s: S) => $, [A, never, never]>): Viewer; /** * Construct a Modifier(modify: (modifyFn: (a: A) => A) => (s: S) => S): Modifier; /** * Construct a Reviewer from a review function. * * @since 2.0.0 */ export declare function reviewer(review: (a: A) => S): Reviewer; /** * Construct an Optic & Reviewer from a tag as well as view, * modify, and reivew functions. * * @since 2.0.0 */ export declare function optic(tag: U, view: (s: S) => $, [A, never, never]>, modify: (modifyFn: (a: A) => A) => (s: S) => S, review: (a: A) => S): Optic & Reviewer; /** * Construct an Optic from a tag as well as view and modify functions. * * @since 2.0.0 */ export declare function optic(tag: U, view: (s: S) => $, [A, never, never]>, modify: (modifyFn: (a: A) => A) => (s: S) => S): Optic; /** * Construct a Lens from view and modify functions. * * @example * ```ts * import type { NonEmptyArray } from "./array.ts"; * * import * as O from "./optic.ts"; * import * as A from "./array.ts"; * import { pipe } from "./fn.ts"; * * const head = () => O.lens, A>( * ([head]) => head, * mod => ([head, ...rest]) => [mod(head), ...rest], * ); * * const headNum = head(); * * const result1 = headNum.view(A.array(1, 2, 3)); // 1 * const result2 = headNum.modify((n: number) => n + 100)(A.array(1, 2, 3)); * // [100, 2, 3] * ``` * * @since 2.0.0 */ export declare function lens(view: (s: S) => A, modify: (modifyFn: (a: A) => A) => (s: S) => S): Lens; /** * Construct an Iso from view and review functions, with an optional * modify function if it is different from * * @example * ```ts * import * as O from "./optic.ts"; * import { Option, match, some, none, map, fromPredicate } from "./option.ts"; * import { pipe, identity } from "./fn.ts"; * * const { view, review, modify }: O.Iso, number> = O.iso( * match(() => 0, identity), * fromPredicate(n => n !== 0), * map, * ); * * const result1 = view(some(1)); // 1 * const result2 = view(none); // 0 * const result3 = review(1); // Some(1) * const result4 = review(0); // None * const result5 = modify(n => n + 100)(some(1)); // Some(101) * const result6 = modify(n => n + 100)(none); // Some(100) * ``` * * @since 2.0.0 */ export declare function iso(view: (s: S) => A, review: (a: A) => S, modify?: (modifyFn: (a: A) => A) => (s: S) => S): Iso; /** * Construct an AffineFold from view and modify functions. * * @example * ```ts * import type { Either } from "./either.ts"; * * import * as O from "./optic.ts"; * import * as E from "./either.ts"; * * const right = () => O.affineFold, R>( * E.getRight, * E.map, * ); * * const numberRight = right(); * * const result1 = numberRight.view(E.right(1)); // Some(1) * const result2 = numberRight.view(E.left("Hello")); // None * const result3 = numberRight.modify(n => n + 1)(E.right(1)); // Right(2) * const result4 = numberRight.modify(n => n + 1)(E.left("Hello")); * // Left("Hello") * ``` * * @since 2.0.0 */ export declare function affineFold(view: (s: S) => Option, modify: (modifyFn: (a: A) => A) => (s: S) => S): AffineFold; /** * Construct a Prism from view and review functions, with an optional * modify function that will be defaulted if not provided. * * @example * ```ts * import * as O from "./optic.ts"; * import * as Op from "./option.ts"; * * const key = (key: string) => () => * O.prism, A>( * rec => Op.fromNullable(rec[key]), * a => ({ [key]: a }), * mod => s => Object.hasOwn(s, key) ? ({ ...s, [key]: mod(s[key]) }) : s, * ); * * const atFoo = key("foo")(); * * const result1 = atFoo.view({ bar: 1 }); // None * const result2 = atFoo.view({ foo: 2 }); // Some(2) * const result3 = atFoo.review(5); // { foo: 5 } * const result4 = atFoo.modify(n => n + 1)({ bar: 1 }); // { bar: 1 } * const result5 = atFoo.modify(n => n + 1)({ foo: 1 }); // { foo: 2 } * const result6 = atFoo.modify(n => n + 1)({ foo: 1, bar: 2 }); * // { foo: 2, bar: 2 } * ``` * * @since 2.0.0 */ export declare function prism(view: (s: S) => Option, review: (a: A) => S, modify?: (modifyFn: (a: A) => A) => (s: S) => S): Prism; /** * Construct a Fold from view and modify functions. * * @example * ```ts * import * as O from "./optic.ts"; * import * as R from "./record.ts"; * * const values = () => O.fold, A>( * Object.values, * R.map, * ); * * const numberValues = values(); * * const result1 = numberValues.view({}); // [] * const result2 = numberValues.view({ foo: 1 }); // [1] * const result3 = numberValues.modify(n => n + 1)({}); // {} * const result4 = numberValues.modify(n => n + 1)({ foo: 1 }); // { foo: 2 } * ``` * * @since 2.0.0 */ export declare function fold(view: (s: S) => ReadonlyArray, modify: (modifyFn: (a: A) => A) => (s: S) => S): Fold; /** * Construct a Refold from view, review, and modify functions. * * @example * ```ts * import * as O from "./optic.ts"; * import * as S from "./set.ts"; * * const set = () => O.refold, A>( * Array.from, * S.wrap, * S.map, * ); * * const numberSet = set(); * * const result1 = numberSet.view(S.set(1, 2, 3)); // [1, 2, 3] * const result2 = numberSet.view(S.init()); // [] * const result3 = numberSet.review(1); // Set(1) * const result4 = numberSet.modify(n => n + 1)(S.wrap(1)); // Set(2) * ``` * * @since 2.0.0 */ export declare function refold(view: (s: S) => ReadonlyArray, review: (a: A) => S, modify: (modifyFn: (a: A) => A) => (s: S) => S): Refold; /** * Construct a Prism from a Refinement. * * @example * ```ts * import type { NonEmptyArray } from "./array.ts"; * * import * as O from "./optic.ts"; * * const isNonEmpty = (arr: ReadonlyArray): arr is NonEmptyArray => * arr.length > 0; * const noninit = O.fromPredicate(isNonEmpty); * * const result1 = noninit.view([]); // None * const result2 = noninit.view([1]); // Some([1]) as NonEmptyArray * const result3 = noninit.review([1]); // [1] Cast NonEmptyArray as Array * ``` * * @since 2.0.0 */ export declare function fromPredicate(refinement: Refinement): Prism; /** * Construct a Prism from a Predicate. * * @example * ```ts * import * as O from "./optic.ts"; * * const positive = O.fromPredicate((n: number) => n > 0); * * const result1 = positive.view(1); // Some(1) * const result2 = positive.view(0); // None * const result3 = positive.review(0); // 0 * const result4 = positive.modify(n => n + 1)(0); // 0 * const result5 = positive.modify(n => n + 1)(1); // 2 * ``` * * @since 2.0.0 */ export declare function fromPredicate(predicate: Predicate): Prism; /** * A pipeable view function that applies a value S to a Viewer. It will * return either a raw value, an option, or a readonlyarray based on the tag of * the Viewer. Note: All Optics are Viewers. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * type Foo = { readonly bar: number }; * * const bar = pipe(O.id(), O.prop("bar")); * * const result = pipe(bar, O.view({ bar: 1 })); // 1 * ``` * * @since 2.0.0 */ export declare function view(s: S): (viewer: Viewer) => ReturnType; /** * A pipeable modify function that applies a modification function to a * Modifier modify function. It will return a function S -> S that applies * the modify function according to the type of optic. Note: All Optics are * Modifiers. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * type Person = { readonly name: string }; * * const name = pipe(O.id(), O.prop("name")); * * const upper = pipe(name, O.modify(s => s.toUpperCase())); * * const result1 = upper({ name: "brandon" }); // { name: "BRANDON" } * ``` * * @since 2.0.0 */ export declare function modify(faa: (a: A) => A): (modifier: Modifier) => ReturnType; /** * A pipeable replace function, that uses the modify function of an Optic to * replace an existing value over the structure S. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * type Person = { name: string }; * * const name = pipe(O.id(), O.prop("name")); * const toBrandon = pipe(name, O.replace("Brandon")); * * const tina: Person = { name: "Tina" } * * const result = toBrandon(tina); // { name: "Brandon" } * ``` * * @since 2.0.0 */ export declare function replace(a: A): (modifier: Modifier) => (s: S) => S; /** * A pipeable review function that applies a value A to the the review function * of a Reviewer. It returns a value S. * * @example * ```ts * import * as O from "./optic.ts"; * import * as S from "./set.ts"; * import { pipe } from "./fn.ts"; * * const numberSet = O.refold, number>( * Array.from, * S.wrap, * S.map, * ); * * const result = pipe(numberSet, O.review(1)); // ReadonlySet(1) * ``` * * @since 2.0.0 */ export declare function review(a: A): (reviewer: Reviewer) => S; /** * Construct an Iso from a type level argument. This is the entrypoint to * almost all optics as it allows one to start with a type and compose other * optics from there. * * @example * ```ts * import * as O from "./optic.ts"; * * const number = O.id(); * * const result1 = number.view(1); // 1 * const result2 = number.review(1); // 1 * const result4 = number.modify(n => n + 1)(1); // 2 * ``` * * @since 2.0.0 */ export declare function id(): Iso; /** * Compose two optics, aligning their tag and building the composition using * natural transformations and monadic chaining for the view function and using * direct composition for the modify function. * * The general algorithm for optic composition in fun is: * * 1. Finding the alignment of them, which is Max where * Fold > AffineFold > Get * 2. Cast both optics to the alignment tag, one cast will always be * a noop. * 3. Construct a new optic by chaining the view functions first to * second and composing the modify functions second to first. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const even = O.fromPredicate((n: number) => n % 2 === 0); * const positive = O.fromPredicate((n: number) => n > 0); * * const evenPos = pipe( * even, * O.compose(positive), * ); * const addTwo = pipe(evenPos, O.modify(n => n + 2)); * * const result1 = pipe(evenPos, O.view(0)); // None * const result2 = pipe(evenPos, O.view(1)); // None * const result3 = pipe(evenPos, O.view(2)); // Some(2) * const result4 = addTwo(0); // 0 * const result5 = addTwo(1); // 1 * const result6 = addTwo(2); // 2 * ``` * * @since 2.0.0 */ export declare function compose(second: Optic): (first: Optic) => Optic, S, I>; /** * Compose two reviewer functions, allowing one to create nested Reviewer * structures. * * @example * ```ts * import * as O from "./optic.ts"; * import * as S from "./set.ts"; * import { pipe } from "./fn.ts"; * * const set = () => O.refold, A>( * Array.from, * S.wrap, * S.map, * ); * * const sets = pipe( * set>(), * O.composeReviewer(set()), * ); * * const result = sets.review(1); // Set(Set(1)) * ``` * * @since 2.0.0 */ export declare function composeReviewer(second: Reviewer): (first: Reviewer) => Reviewer; /** * Construct a Lens Viewer from a raw value A. The view function of this viewer * operatates like constant(a). * * @example * ```ts * import * as O from "./optic.ts"; * * const viewer = O.wrap(1); * * const result1 = viewer.view(2); // 1 * const result2 = viewer.view(100); // 1 * ``` * * @since 2.0.0 */ export declare function wrap(a: A): Viewer; /** * An invariant map over an Optic. If a type can be represented isomorphically * by another type, one can imap to go back and forth. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const plussed = pipe( * O.id(), * O.imap(n => n + 100, n => n - 100), * ); * * const result1 = plussed.view(1); // 101 * const result2 = plussed.modify(n => n + 1)(1); // 2 * ``` * * @since 2.0.0 */ export declare function imap(fai: (a: A) => I, fia: (i: I) => A): (first: Optic) => Optic, S, I>; /** * A composable combinator that focuses on a property P of a struct. * * @example * ```ts * import * as O from "./optic.ts"; * import { toUpperCase } from "./string.ts"; * import { pipe } from "./fn.ts"; * * type Person = { name: string, age: number }; * * const person = O.id(); * const name = pipe(person, O.prop("name")); * const age = pipe(person, O.prop("age")); * * const brandon: Person = { name: "Brandon", age: 37 }; * const emily: Person = { name: "Emily", age: 35 }; * * const result1 = pipe(name, O.view(brandon)); // "Brandon" * const result2 = pipe(name, O.view(emily)); // "Emily" * const result3 = pipe(age, O.view(brandon)); // 37 * const result4 = pipe(brandon, name.modify(toUpperCase)); * // { name: "BRANDON", age: 37 } * ``` * * @since 2.0.0 */ export declare function prop(prop: P): (sa: Optic) => Optic, S, A[P]>; /** * A composible combinator that focuses on a list of properties of a struct. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * type Book = { * title: string, * description: string, * authors: readonly string[], * published: Date, * }; * * const short = pipe(O.id(), O.props("title", "description")); * * const suttree: Book = { * title: "Suttree", * description: "Cormac on Cormac", * authors: ["Cormac McCarthy"], * published: new Date("May 01 1979"), * }; * * const result1 = pipe(short, O.view(suttree)); * // { title: "Suttree", description: "Cormac on Cormac" } * ``` * * @since 2.0.0 */ export declare function props, P extends keyof A>(...props: [P, P, ...Array

]): (first: Optic) => Optic, S, { [K in P]: A[K]; }>; /** * A composible combinator that focuses on a value in an array at the given * index. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const second = pipe( * O.id>(), * O.index(1), * ); * * const result1 = pipe(second, O.view([])); // None * const result2 = pipe(second, O.view(["Hello", "World"])); // Some("World") * ``` * * @since 2.0.0 */ export declare function index(index: number): (first: Optic>) => Optic, S, A>; /** * A composible combinator that focuses on a key in a readonly record. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const one = pipe( * O.id>>(), * O.key("one"), * ); * * const result1 = pipe(one, O.view({})); // None * const result2 = pipe(one, O.view({ one: "one" })); // Some("one") * ``` * * @since 2.0.0 */ export declare function key(key: string): (first: Optic>) => Optic, S, A>; /** * A composible combinator that focuses on a key in a readonly record. The * difference between atKey and key is that the key can be removed from the * record by the modify function if the modify function returns None. * * @example * ```ts * import * as O from "./optic.ts"; * import { constNone } from "./option.ts"; * import { pipe } from "./fn.ts"; * * const atOne = pipe( * O.id>>(), * O.atKey("one"), * ); * const removeAtOne = pipe(atOne, O.replace(constNone())); * * const result1 = pipe(atOne, O.view({})); // None * const result2 = pipe(atOne, O.view({ one: "one" })); // Some("one") * const result3 = removeAtOne({}); // {} * const result4 = removeAtOne({ one: "one" }); // {} * const result5 = removeAtOne({ one: "one", two: "two" }); // { two: "two" } * ``` * * @since 2.0.0 */ export declare function atKey(key: string): (first: Optic>>) => Optic, S, Option>; /** * A composible combinator that can filter or refine the focused value of an * existing optic. Care should be taken with this operator as it apples to the * modify function as well as the view function. That is to say that if the * refinement or predicate returns false for the focused value then that value * will not be modified. See the example for clarification. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const positive = pipe(O.id(), O.filter(n => n > 0)); * * const result1 = pipe(positive, O.view(1)); // Some(1); * const result2 = pipe(positive, O.view(0)); // None * const result3 = pipe(1, positive.modify(n => n + 1)); // 2 * const result4 = pipe(0, positive.modify(n => n + 1)); // 0 * ``` * * @since 2.0.0 */ export declare function filter(r: Refinement): (first: Optic) => Optic, S, B>; export declare function filter(r: Predicate): (first: Optic) => Optic, S, A>; /** * Construct a composable combinator from an instance of Comparable and a key of a map. * The combinator can then be composed with an existing optic to access or * remove the value in the map. * * @example * ```ts * import * as O from "./optic.ts"; * import * as M from "./map.ts"; * import { ComparableString, toLowerCase } from "./string.ts"; * import { premap } from "./comparable.ts"; * import { constNone } from "./option.ts"; * import { pipe } from "./fn.ts"; * * type Words = ReadonlyMap; * * const insensitive = pipe(ComparableString, premap(toLowerCase)); * * const fun = pipe(O.id(), O.atMap(insensitive)("fun")); * const remove = pipe(fun, O.replace(constNone())); * * const result1 = pipe(fun, O.view(new Map([["FUN", 100]]))); // Some(100) * const result2 = pipe(fun, O.view(M.init())); // None * const result3 = remove(new Map([["FUN", 100], ["not", 10]])); * // Map("not": 10); * ``` * * @since 2.0.0 */ export declare function atMap(eq: Comparable): (key: B) => (first: Optic>) => Optic, S, Option>; /** * Construct a composable optic from a Traversable instance for a Kind T. This * will fold the values wrapped in the Kind T into a single Array when viewed. * * @example * ```ts * import * as O from "./optic.ts"; * import * as T from "./tree.ts"; * import { pipe } from "./fn.ts"; * * type Data = { tree: T.Tree }; * * const numbers = pipe( * O.id(), * O.prop("tree"), * O.traverse(T.TraversableTree), * ); * * const tree1: Data = { tree: T.tree(1, [T.tree(2), T.tree(3)]) }; * const tree2: Data = { tree: T.tree(0) }; * * const result1 = pipe(numbers, O.view(tree1)); // [1, 2, 3] * const result2 = pipe(numbers, O.view(tree2)); // [0] * const result3 = pipe(tree1, numbers.modify(n => n + 1)); * // Tree(2, [Tree(3), Tree(4)]) * ``` * * @since 2.0.0 */ export declare function traverse(T: Traversable): (first: Optic>) => Optic, S, A>; /** * Given a Combinable and a function A -> I, collect all values A focused on by an * optic into a single value I. * * @example * ```ts * import * as O from "./optic.ts"; * import { InitializableNumberSum } from "./number.ts"; * import { pipe, identity } from "./fn.ts"; * * type Person = { name: string, age: number }; * type People = readonly Person[]; * * const cumulativeAge = pipe( * O.id(), * O.array, * O.prop("age"), * O.combineAll(InitializableNumberSum, identity), * ); * * const people: People = [ * { name: "Brandon", age: 37 }, * { name: "Emily", age: 22 }, * { name: "Jackie", age: 47 }, * { name: "Rufus", age: 1 }, * ]; * * const result1 = cumulativeAge(people); // 107 * const result2 = cumulativeAge([]); // 0 * ``` * * @since 2.0.0 */ export declare function combineAll(initializable: Initializable, fai: (a: A) => I): (first: Optic) => (s: S) => I; /** * A preconstructed traversal that focuses the values of a ReadonlyRecord. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const result = pipe( * O.id>>(), * O.record, * O.view({ one: 1, two: 2 }), * ); // [1, 2] * ``` * * @since 2.0.0 */ export declare const record: (first: Optic>) => Optic, S, A>; /** * A preconstructed traversal that focuses the values of a ReadonlyArray. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const result = pipe( * O.id>(), * O.array, * O.filter(n => n % 2 === 0), * O.view([1, 2, 3]), * ); // [2] * ``` * * @since 2.0.0 */ export declare const array: (first: Optic>) => Optic, S, A>; /** * A preconstructed traversal that focuses the values of a ReadonlySet. * * @example * ```ts * import * as O from "./optic.ts"; * import { pipe } from "./fn.ts"; * * const result = pipe( * O.id>(), * O.set, * O.view(new Set([1, 2, 3])), * ); // [1, 2, 3] * ``` * * @since 2.0.0 */ export declare const set: (first: Optic>) => Optic, S, A>; /** * A preconstructed traversal that focuses the values of a Tree. * * @example * ```ts * import type { Tree } from "./tree.ts"; * import * as O from "./optic.ts"; * import * as T from "./tree.ts"; * import { pipe } from "./fn.ts"; * * const result = pipe( * O.id>(), * O.tree, * O.view(T.tree(1, [T.tree(2, [T.tree(3)])])), * ); // [1, 2, 3] * ``` * * @since 2.0.0 */ export declare const tree: (first: Optic>) => Optic, S, A>; /** * A preconstructed filter that focuses on the the non-null and non-undefined * value of A | null | undefined. * * @example * ```ts * import * as O from "./optic.ts"; * import { constNone } from "./option.ts"; * import { pipe } from "./fn.ts"; * * type Input = { value?: string | null }; * * const value = pipe(O.id(), O.prop("value"), O.nil); * * const result1 = pipe(value, O.view({})); // None * const result2 = pipe(value, O.view({ value: "Hello" })); // Some("Hello") * ``` * * @since 2.0.0 */ export declare const nil: (first: Optic) => Optic, S, NonNullable>; /** * A preconstructed composed prism that focuses on the Some value of an Option. * * @example * ```ts * import * as O from "./optic.ts"; * import { Option, some, none } from "./option.ts"; * import { pipe } from "./fn.ts"; * * type Person = { name: string, talent: Option }; * type People = readonly Person[] * * const talent = pipe(O.id(), O.array, O.prop("talent"), O.some); * * const brandon: Person = { name: "Brandon", talent: none }; * const emily: Person = { name: "Emily", talent: some("Knitting") }; * * const result = pipe(talent, O.view([brandon, emily])); // ["Knitting"]; * ``` * * @since 2.0.0 */ export declare const some: (optic: Optic>) => Optic, S, A>; /** * A preconstructed composed prism that focuses on the Right value of an Either. * * @example * ```ts * import * as O from "./optic.ts"; * import * as E from "./either.ts"; * import { pipe } from "./fn.ts"; * * type Response = E.Either; * * const value = pipe(O.id(), O.right); * * const result1 = pipe(value, O.view(E.right("Good job!"))); * // Some("Good job!") * const result2 = pipe(value, O.view(E.left(new Error("Something broke")))); * // None * ``` * * @since 2.0.0 */ export declare const right: (optic: Optic>) => Optic, S, A>; /** * A preconstructed composed prism that focuses on the Left value of an Either. * * @example * ```ts * import * as O from "./optic.ts"; * import * as E from "./either.ts"; * import { pipe } from "./fn.ts"; * * type Response = E.Either; * * const value = pipe(O.id(), O.left); * * const result1 = pipe(value, O.view(E.right("Good job!"))); * // None * const result2 = pipe(value, O.view(E.left(new Error("Something broke")))); * // Some(Error("Something broke")) * ``` * * @since 2.0.0 */ export declare const left: (optic: Optic>) => Optic, S, B>; /** * A preconstructed composed lens that focuses on the First value of a Pair. * * @example * ```ts * import * as O from "./optic.ts"; * import * as P from "./pair.ts"; * import { pipe } from "./fn.ts"; * * // Pair * type Rational = P.Pair; * * const numerator = pipe(O.id(), O.first); * * const result = pipe(numerator, O.view(P.pair(1, 1))); // 1 * ``` * * @since 2.0.0 */ export declare const first: (optic: Optic>) => Optic, S, A>; /** * A preconstructed composed lens that focuses on the Second value of a Pair. * * @example * ```ts * import * as O from "./optic.ts"; * import * as P from "./pair.ts"; * import { pipe } from "./fn.ts"; * * // Pair * type Rational = P.Pair * * const denominator = pipe(O.id(), O.first); * * const result = pipe(denominator, O.view(P.pair(1, 2))); // 2 * ``` * * @since 2.0.0 */ export declare const second: (optic: Optic>) => Optic, S, B>; export {};