// @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)
}