// ets_tracing: off /** * A `Lens` is an optic used to zoom inside a product. * * `Lens`es have two type parameters generally called `S` and `A`: `Lens` where `S` represents the product and `A` * an element inside of `S`. * * Laws: * * 1. get(set(a)(s)) = a * 2. set(get(s))(s) = s * 3. set(a)(set(a)(s)) = set(a)(s) */ import type { Either } from "@effect-ts/core/Either" import type { Predicate, Refinement } from "@effect-ts/core/Function" import { flow, pipe } from "@effect-ts/core/Function" import type { Option } from "@effect-ts/core/Option" import type { URI } from "@effect-ts/core/Prelude" import * as P from "@effect-ts/core/Prelude" import type { HashMap } from "@effect-ts/system/Collections/Immutable/HashMap" import * as _ from "../Internal/index.js" import { Lens } from "../Internal/index.js" import type { Optional } from "../Optional/index.js" import type { Prism } from "../Prism/index.js" import type { Traversal } from "../Traversal/index.js" // ------------------------------------------------------------------------------------- // model // ------------------------------------------------------------------------------------- export { Lens } // ------------------------------------------------------------------------------------- // constructors // ------------------------------------------------------------------------------------- export const id: () => Lens = _.lensId // ------------------------------------------------------------------------------------- // converters // ------------------------------------------------------------------------------------- /** * View a `Lens` as a `Optional` */ export const asOptional: (sa: Lens) => Optional = _.lensAsOptional /** * View a `Lens` as a `Traversal` */ export const asTraversal: (sa: Lens) => Traversal = _.lensAsTraversal // ------------------------------------------------------------------------------------- // compositions // ------------------------------------------------------------------------------------- /** * Compose a `Lens` with a `Lens` */ export const compose: (ab: Lens) => (sa: Lens) => Lens = _.lensComposeLens /** * Compose a `Lens` with a `Prism` */ export const composePrism: ( ab: Prism ) => (sa: Lens) => Optional = _.lensComposePrism /** * Compose a `Lens` with an `Optional` */ export const composeOptional = (ab: Optional) => (sa: Lens): Optional => _.optionalComposeOptional(ab)(asOptional(sa)) // ------------------------------------------------------------------------------------- // combinators // ------------------------------------------------------------------------------------- export const modify = (f: (a: A) => A) => (sa: Lens) => (s: S): S => { const o = sa.get(s) const n = f(o) return o === n ? s : sa.set(n)(s) } /** * Return a `Optional` from a `Lens` focused on a nullable value */ export const fromNullable = (sa: Lens): Optional> => _.lensComposePrism(_.prismFromNullable())(sa) export function filter( refinement: Refinement ): (sa: Lens) => Optional export function filter( predicate: Predicate ): (sa: Lens) => Optional export function filter( predicate: Predicate ): (sa: Lens) => Optional { return composePrism(_.prismFromPredicate(predicate)) } /** * Return a `Lens` from a `Lens` and a prop */ export const prop: ( prop: P ) => (sa: Lens) => Lens = _.lensProp /** * Return a `Lens` from a `Lens` and a list of props */ export const props: ( ...props: [P, P, ...Array

] ) => (sa: Lens) => Lens = _.lensProps /** * Return a `Lens` from a `Lens` and a component */ export const component: , P extends keyof A>( prop: P ) => (sa: Lens) => Lens = _.lensComponent /** * Return a `Optional` from a `Lens` focused on a `ReadonlyArray` */ export const index = (i: number) => (sa: Lens>): Optional => pipe(sa, asOptional, _.optionalComposeOptional(_.indexArray().index(i))) /** * Return a `Optional` from a `Lens` focused on a `ReadonlyRecord` and a key */ export const keyInRecord = (key: string) => (sa: Lens>>): Optional => pipe(sa, asOptional, _.optionalComposeOptional(_.indexRecord().index(key))) /** * Return a `Lens` from a `Lens` focused on a `ReadonlyRecord` and a required key */ export const atKeyInRecord = (key: string) => (sa: Lens>>): Lens> => pipe(sa, compose(_.atRecord().at(key))) /** * Return a `Optional` from a `Lens` focused on a `HashMap` and a key */ export const keyInHashMap = (key: K) => (sa: Lens>>): Optional => pipe(sa, asOptional, _.optionalComposeOptional(_.indexHashMap().index(key))) /** * Return a `Lens` from a `Lens` focused on a `HashMap` and a required key */ export const atKeyInHashMap = (key: K) => (sa: Lens>>): Lens> => pipe(sa, compose(_.atHashMap().at(key))) /** * Return a `Optional` from a `Lens` focused on the `Some` of a `Option` type */ export const some: (soa: Lens>) => Optional = composePrism( _.prismSome() ) /** * Return a `Optional` from a `Lens` focused on the `Right` of a `Either` type */ export const right: (sea: Lens>) => Optional = composePrism(_.prismRight()) /** * Return a `Optional` from a `Lens` focused on the `Left` of a `Either` type */ export const left: (sea: Lens>) => Optional = composePrism(_.prismLeft()) /** * Pipeable set */ export const set = (a: A) => (lens: Lens) => lens.set(a) /** * Pipeable get */ export const get = (lens: Lens) => lens.get /** * Return a `Traversal` from a `Lens` focused on a `ForEach` */ export function forEach( T: P.ForEach ): ( sta: Lens> ) => Traversal { return flow(asTraversal, _.traversalComposeTraversal(_.fromForEach(T)())) } export const find: ( predicate: Predicate ) => (sa: Lens>) => Optional = flow( _.find, composeOptional ) // ------------------------------------------------------------------------------------- // pipeables // ------------------------------------------------------------------------------------- export const imap: ( f: (a: A) => B, g: (b: B) => A ) => (sa: Lens) => Lens = (f, g) => (ea) => new Lens({ get: flow(ea.get, f), set: flow(g, ea.set) }) // ------------------------------------------------------------------------------------- // instances // ------------------------------------------------------------------------------------- export const LensURI = "monocle/Lens" export type LensURI = typeof LensURI declare module "@effect-ts/core/Prelude/HKT" { export interface URItoKind { [LensURI]: Lens } } export const Category = P.instance]>>({ compose, id }) export const Invariant = P.instance]>>({ invmap: ({ f, g }) => ({ f: imap(f, g), g: imap(g, f) }) })