// @flow import type { Fold } from './Fold' import type { PSetter } from './PSetter' import type { Monoid } from './Monoid' import type { Applicative } from './Applicative' import type { Traversable } from './Traversable' /* A Traversal is the generalisation of an Optional to several targets. In other word, a Traversal allows to focus from a type S into 0 to n values of type A. The most common example of a Traversal would be to focus into all elements inside of a container (e.g. List, Maybe). */ import { HKT } from './HKT' import { getApplicative, inj, prj } from './Const' import * as id from './Identity' export interface PTraversal { modifyF(applicative: Applicative, f: (a: A) => HKT, s: S): HKT } export type Traversal = PTraversal; export function modify(traversal: PTraversal, f: (a: A) => B, s: S): T { return id.extract(traversal.modifyF(id, a => id.of(f(a)), s)) } export function asFold(traversal: PTraversal): Fold { return { foldMap(monoid: Monoid, f: (a: A) => M, s: S): M { return prj(traversal.modifyF(getApplicative(monoid), a => inj(f(a)), s)) } } } export function asSetter(traversal: PTraversal): PSetter { return { modify(f: (a: A) => B, s: S): T { return modify(traversal, f, s) } } } export function composeTraversal(ab: PTraversal, st: PTraversal): PTraversal { return { modifyF(applicative: Applicative, f: (c: C) => HKT, s: S): HKT { return st.modifyF(applicative, c => ab.modifyF(applicative, f, c), s) } } } export function fromTraversable(traversable: Traversable): PTraversal, HKT, A, B> { return { modifyF(applicative: Applicative, f: (a: A) => HKT, s: HKT): HKT> { return traversable.traverse(applicative, f, s) } } }