// ets_tracing: off /** * A `Prism` is an optic used to select part of a sum type. * * Laws: * * 1. getOption(s).fold(s, reverseGet) = s * 2. getOption(reverseGet(a)) = Some(a) */ import type { Either } from "@effect-ts/core/Either" import type { Predicate, Refinement } from "@effect-ts/core/Function" import { flow, identity, pipe } from "@effect-ts/core/Function" import type { Newtype } from "@effect-ts/core/Newtype" import * as O 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 { composePrism as compose, Prism } from "../Internal/index.js" import type { Lens } from "../Lens/index.js" import type { Optional } from "../Optional/index.js" import type { Traversal } from "../Traversal/index.js" import Option = O.Option // ------------------------------------------------------------------------------------- // model // ------------------------------------------------------------------------------------- export { Prism } // ------------------------------------------------------------------------------------- // constructors // ------------------------------------------------------------------------------------- export const id = (): Prism => new Prism({ getOption: O.some, reverseGet: identity }) export const fromPredicate: { (refinement: Refinement): Prism (predicate: Predicate): Prism } = _.prismFromPredicate // ------------------------------------------------------------------------------------- // converters // ------------------------------------------------------------------------------------- /** * View a `Prism` as a `Optional` */ export const asOptional: (sa: Prism) => Optional = _.prismAsOptional /** * View a `Prism` as a `Traversal` */ export const asTraversal: (sa: Prism) => Traversal = _.prismAsTraversal // ------------------------------------------------------------------------------------- // compositions // ------------------------------------------------------------------------------------- export { compose } /** * Compose a `Prism` with a `Lens` */ export const composeLens: ( ab: Lens ) => (sa: Prism) => Optional = _.prismComposeLens /** * Compose a `Prism` with an `Optional` */ export const composeOptional = (ab: Optional) => (sa: Prism): Optional => _.optionalComposeOptional(ab)(asOptional(sa)) // ------------------------------------------------------------------------------------- // combinators // ------------------------------------------------------------------------------------- export const set: (a: A) => (sa: Prism) => (s: S) => S = _.prismSet export const modifyOption: ( f: (a: A) => A ) => (sa: Prism) => (s: S) => Option = _.prismModifyOption export const modify: (f: (a: A) => A) => (sa: Prism) => (s: S) => S = _.prismModify /** * Return a `Prism` from a `Prism` focused on a nullable value */ export const fromNullable: (sa: Prism) => Prism> = compose(_.prismFromNullable()) export function filter( refinement: Refinement ): (sa: Prism) => Prism export function filter(predicate: Predicate): (sa: Prism) => Prism export function filter( predicate: Predicate ): (sa: Prism) => Prism { return compose(_.prismFromPredicate(predicate)) } /** * Return a `Optional` from a `Prism` and a prop */ export const prop = ( prop: P ): ((sa: Prism) => Optional) => composeLens(pipe(_.lensId(), _.lensProp(prop))) /** * Return a `Optional` from a `Prism` and a list of props */ export const props = ( ...props: [P, P, ...Array

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