// @flow import type { HKT2 } from './HKT' import type { Setoid } from './Setoid' import type { Semigroupoid } from './Semigroupoid' import type { Semigroup } from './Semigroup' import type { Monoid } from './Monoid' import type { Functor } from './Functor' import type { Contravariant } from './Contravariant' import type { Apply } from './Apply' import type { Applicative } from './Applicative' import type { Chain } from './Chain' import { HKT } from './HKT' // The `Const` type constructor, which wraps its first type argument // and ignores its second. That is, `Const a b` is isomorphic to `a` // for any `b`. // // `Const` has some useful instances. For example, the `Applicative` // instance allows us to collect results using a `Monoid` while // ignoring return values. class IsConst {} export type ConstV = A; // eslint-disable-line no-unused-vars export type Const = HKT2; export type ConstF = HKT; export function inj(a: ConstV): Const { return ((a: any): Const) } export function prj(a: Const): ConstV { return ((a: any): ConstV) } export function compose(x: Const, y: Const): Const { return ((y: any): Const) } export function map(f: (a: A) => B, fa: Const): Const { return ((fa: any): Const) } export function contramap(f: (b: B) => A, fa: Const): Const { return ((fa: any): Const) } export function getSetoid(setoid: Setoid): Setoid> { return { equals(x: Const, y: Const): boolean { return setoid.equals(prj(x), prj(y)) } } } export function getSemigroup(semigroup: Semigroup): Semigroup> { return { concat(x: Const, y: Const): Const { return inj(semigroup.concat(prj(x), prj(y))) } } } export function getMonoid(monoid: Monoid): Monoid> { const { concat } = getSemigroup(monoid) const empty: Const = inj(monoid.empty()) return { concat, empty(): Const { return empty } } } export function getApply(semigroup: Semigroup): Apply> { return { map, ap(fab: Const B>, fa: Const): Const { const x = prj(fab) const y = prj(fa) return inj(semigroup.concat(x, y)) } } } export function getApplicative(monoid: Monoid): Applicative> { const { map, ap } = getApply(monoid) return { map, ap, of(b: B): Const { // eslint-disable-line no-unused-vars return inj(monoid.empty()) } } } export function getChain(semigroup: Semigroup): Chain> { const { map, ap } = getApply(semigroup) return { map, ap, chain(f: (a: A) => Const, fa: Const): Const { return ((fa: any): Const) } } } if (false) { // eslint-disable-line ({ compose, map, contramap }: Functor & Contravariant & Semigroupoid) }