// @flow import type { Either } from './Either' import type { Maybe } from './Maybe' import type { POptional } from './POptional' import * as either from './Either' import * as maybe from './Maybe' import { id } from './Identity' export interface PPrism { getOrModify(s: S): Either, reverseGet(b: B): T } export type Prism = PPrism; export function modify(stab: PPrism, f: (a: A) => B, s: S): T { return either.either(id, a => stab.reverseGet(f(a)), stab.getOrModify(s)) } export function createSSAB(getOption: (s: S) => Maybe, reverseGet: (b: B) => S): PPrism { return { getOrModify(s: S): Either { return maybe.maybe(either.left(s), either.right, getOption(s)) }, reverseGet } } export function asOptional(prism: PPrism): POptional { return { getOrModify: prism.getOrModify, set(b: B): T { return prism.reverseGet(b) } } } export function composePrism(abcd: PPrism, stab: PPrism): PPrism { return { getOrModify(s: S): Either { return either.chain( a => either.bimap( stab.reverseGet, id, abcd.getOrModify(a) ), stab.getOrModify(s) ) }, reverseGet(d: D): T { return stab.reverseGet(abcd.reverseGet(d)) } } }