// @flow import { HKT } from './HKT' import type { Setoid } from './Setoid' import type { Ord } from './Ord' import type { Semigroup } from './Semigroup' import type { Monoid } from './Monoid' import type { Applicative } from './Applicative' import type { Monad } from './Monad' import type { Foldable } from './Foldable' import type { Traversable } from './Traversable' import type { Alt } from './Alt' import type { Extend } from './Extend' import type { Comonad } from './Comonad' import type { ChainRec } from './ChainRec' import type { Either } from './Either' import { tailRec } from './ChainRec' import { compose } from './Fun' class IsIdentity {} export type Identity = HKT; function prj(fa: HKT): A { return ((fa: any): A) } function inj(a: A): HKT { return ((a: any): HKT) } export function id(a: A): A { return a } export function map(f: (a: A) => B, fa: Identity): Identity { return inj(f(prj(fa))) } export function ap(fab: Identity<(a: A) => B>, fa: Identity): Identity { return map(prj(fab), fa) } export const of = inj export function chain(f: (a: A) => Identity, fa: Identity): Identity { return f(prj(fa)) } export function reduce(f: (b: B, a: A) => B, b: B, fa: Identity): B { return f(b, prj(fa)) } export function alt(fx: Identity, fy: Identity): Identity { // eslint-disable-line no-unused-vars return fx } export function traverse(applicative: Applicative, f: (a: A) => HKT, ta: Identity): HKT> { return applicative.map(of, f(prj(ta))) } export function extend(f: (ea: Identity) => B, ea: Identity): Identity { return of(f(ea)) } export const extract = prj export function chainRec(f: (a: A) => Identity>, a: A): Identity { return inj(tailRec(compose(extract, f), a)) } export function getSetoid(setoid: Setoid): Setoid> { return { equals(fx, fy) { return setoid.equals(prj(fx), prj(fy)) } } } export function getOrd(ord: Ord): Ord> { return { equals: getSetoid(ord).equals, compare(fx, fy) { return ord.compare(prj(fx), prj(fy)) } } } export function getSemigroup(semigroup: Semigroup): Semigroup> { return { concat(fx, fy) { return inj(semigroup.concat(prj(fx), prj(fy))) } } } export function getMonoid(monoid: Monoid): Monoid> { return { concat: getSemigroup(monoid).concat, empty() { return inj(monoid.empty()) } } } if (false) { // eslint-disable-line ({ map, ap, of, chain, reduce, alt, traverse, extend, extract, chainRec }: Monad & Foldable & Traversable & Alt & Extend & Comonad & ChainRec) }