import * as S from "@principia/prelude/Show"; import { memoize } from "../_utils"; import * as A from "../Array"; import { pipe } from "../Function"; import type { ReadonlyRecord } from "../Record"; import * as R from "../Record"; import type { Show } from "./model"; /* * ------------------------------------------- * Show Combinators * ------------------------------------------- */ export * from "@principia/prelude/Show/combinators"; export const named_ = (show: Show, name: string | undefined): Show => S.fromShow((a) => (typeof name !== "undefined" ? `<${name}>(${show.show(a)})` : show.show(a))); export const named = (name: string | undefined) => (show: Show): Show => named_(show, name); export const nullable = (or: Show): Show => S.fromShow((a) => (a === null ? "null" : or.show(a))); export const undefinable = (or: Show): Show => S.fromShow((a) => (typeof a === "undefined" ? "undefined" : or.show(a))); export const type: >>( shows: { [K in keyof A]: Show } ) => Show<{ [K in keyof A]: A[K] }> = S.getStructShow; export const partial = >>( properties: { [K in keyof A]: Show } ): Show> => pipe( properties, R.map((s: Show) => undefinable(s)), type ); export const record: (codomain: Show) => Show> = R.getShow; export const array: (item: Show) => Show> = A.getShow; export const tuple: >( ...components: { [K in keyof A]: Show } ) => Show = S.getTupleShow as any; export const intersect_ = (left: Show, right: Show): Show => S.fromShow((a) => `${left.show(a)} & ${right.show(a)}`); export const intersect = (right: Show) => (left: Show): Show => intersect_(left, right); export const sum_ = ( tag: T, members: { [K in keyof A]: Show> } ): Show => S.fromShow((a: ReadonlyRecord) => members[a[tag]].show(a)); export const sum = (tag: T) => ( members: { [K in keyof A]: Show> } ): Show => sum_(tag, members); export const lazy = (f: () => Show): Show => { const get = memoize>(f); return S.fromShow((a) => get().show(a)); };