Skip to main content
Module

x/fun/optics.ts

A collection of algebraic data types, lenses, and schemables based on a light weight higher kinded type implementation. Written for deno.
Go to Latest
import * as fun from "https://deno.land/x/fun@v.2.0.0-alpha.11/optics.ts";

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.

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.

Variables

A runtime tag and type that indicates an Optic has a view function of the form (s: S) => Option<A>.

A preconstructed traversal that focuses the values of a ReadonlyArray.

A preconstructed composed lens that focuses on the First value of a Pair.

A runtime tag and type that indicates an Optic has a view function of the form (s: S) => ReadonlyArray<A>.

A preconstructed composed prism that focuses on the Left value of an Either.

A runtime tag and type that indicates an Optic has a view function of the form (s: S) => Identity<A>.

A preconstructed filter that focuses on the the non-null and non-undefined value of A | null | undefined.

A preconstructed traversal that focuses the values of a ReadonlyRecord.

A preconstructed composed prism that focuses on the Right value of an Either.

A preconstructed composed lens that focuses on the Second value of a Pair.

A preconstructed traversal that focuses the values of a ReadonlySet.

A preconstructed composed prism that focuses on the Some value of an Option.

A preconstructed traversal that focuses the values of a Tree.

Functions

Given a Viewer<U, S, A> and an optic tag V, this function produces a view function that can be used in a Viewer<V, S, A>. However, not all casts are valid. The following are the only supported casts, by their optic tag:

Construct an AffineFold<S, A> from view and modify functions.

Apply the value returned by a Viewer to a function returned by a Viewer.

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.

Construct a composable combinator from an instance of Eq 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.

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.

Compose two reviewer functions, allowing one to create nested Reviewer structures.

Given a Monoid and a function A -> I, collect all values A focused on by an optic into a single value I.

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.

Construct a Fold<S, A> from view and modify functions.

Construct a Prism<S, A> from a Refinement<S, A>.

Construct an Iso<A, A> 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.

An invariant map over an Optic. If a type can be represented isomorphically by another type, one can imap to go back and forth.

A composible combinator that focuses on a value in an array at the given index.

Construct an Iso<S, A> from view and review functions, with an optional modify function if it is different from

A composible combinator that focuses on a key in a readonly record.

Construct a Lens<S, A> from view and modify functions.

Map over the Viewer portion of an optic. This effectively uses the map from the Monad associated with the tag of the optic.

Construct a Modifier<S, A. from a modify function.

A pipeable modify function that applies a modification function to a Modifier<S, A> 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.

Construct a Lens Viewer from a raw value A. The view function of this viewer operatates like constant(a).

Construct an Optic<U, S, A> & Reviewer<S, A> from a tag as well as view, modify, and reivew functions.

Construct a Prism<S, A> from view and review functions, with an optional modify function that will be defaulted if not provided.

A composable combinator that focuses on a property P of a struct.

A composible combinator that focuses on a list of properties of a struct.

Construct a Refold<S, A> from view, review, and modify functions.

A pipeable replace function, that uses the modify function of an Optic to replace an existing value over the structure S.

A pipeable review function that applies a value A to the the review function of a Reviewer<S, A>. It returns a value S.

Construct a Reviewer<S, A> from a review function.

Construct a composable optic from a Traversable instance for a Kind T. This will reduce the values wrapped in the Kind T into a single Array when viewed.

A pipeable view function that applies a value S to a Viewer<S, A>. It will return either a raw value, an option, or a readonlyarray based on the tag of the Viewer. Note: All Optics are Viewers.

Construct a Viewer<T, S, A> 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.

Interfaces

The Modifier<S, A> 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.

An Optic<T, S, A> is defined as a Viewer<T, S, A> combined with a Modifier<S, A>. This is the root type for the specific types of Optics defined below.

The Reviewer<S, A. type implements the review function (a: A) => S. This type is directly composable and is used when the S type in Viewer<U, S, A> can be reconstructed from A. Some examples are constructing Option<number> from number, Array<number> from number, etc.

A Viewer<T, S, A> implements a view function (s: S) => T<A>. 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.

Type Aliases

AffineFold<S, A> is an alias of Optic<AffineTag, S, A>. This means the view function of an AffineFold returns an Option, (s: S) => Option<A>. 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.

Fold<S, A> is an alias of Optic<FoldTag, S, A>. This means that the view function of a Fold returns a ReadonlyArray, (s: S) => ReadonlyArray<A>. 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.

Iso<S, A> is an alias of Lens<S, A> & Reviewer<S, A>. This means that an Iso operates exactly like a Lens with the added ability to go back from A to S.

Lens<S, A> is an alias of Optic<LensTag, S, A>. 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.

Prism<S, A> is an alias of AffineFold<S, A> & Reviewer<S, A>. 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<string, number> from a string or a number.

Refold<S, A> is an alias of Fold<S, A> & Reviewer<S, A>. 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.

A type union of the supported view tags for a Viewer