// @flow import { HKT } from './HKT' import type { Monad } from './Monad' import type { Semigroup } from './Semigroup' import type { Monoid } from './Monoid' import type { Eff } from './Eff' class IsIO {} export type IOV = () => A; export type IO = HKT; export function inj(a: IOV): IO { return ((a: any): IO) } export function prj(fa: IO): IOV { return ((fa: any): IOV) } export function runIO(eff: IO): A { return prj(eff)() } export function map(f: (a: A) => B, fa: IO): IO { return inj(() => f(runIO(fa))) } export function ap(fab: IO<(a: A) => B>, fa: IO): IO { return inj(() => runIO(fab)(runIO(fa))) } export function of(a: A): IO { return inj(() => a) } export function chain(f: (a: A) => IO, fa: IO): IO { return inj(() => runIO(f(runIO(fa)))) } export function concat(semigroup: Semigroup): (fx: IO, fy: IO) => IO { return function concat(fx, fy) { return inj(() => semigroup.concat(runIO(fx), runIO(fy))) } } export function getSemigroup(semigroup: Semigroup): Semigroup> { return { concat: concat(semigroup) } } export function getMonoid(monoid: Monoid): Monoid> { return { empty: () => of(monoid.empty()), concat: concat(monoid) } } export function fromEff(fa: Eff): IO { return ((fa: any): IO) } export function toEff(fa: IO): Eff { return ((fa: any): Eff) } if (false) { // eslint-disable-line ({ map, ap, of, chain }: Monad) }