UNPKG

@dillonkearns/elm-graphql

Version:

<img src="https://cdn.jsdelivr.net/gh/martimatix/logo-graphqelm/logo.svg" alt="dillonearns/elm-graphql logo" width="40%" align="right">

83 lines (62 loc) 2 kB
// @flow import type { Functor } from './Functor' import type { Monad } from './Monad' import type { HKT2 } from './HKT' import { HKT } from './HKT' import { Data1 } from './Data' class IsFree {} // we can think of a free monad as just being a list of functors class Suspend<F, A> extends Data1<HKT<F, Free<F, A>>> {} class Return<A> extends Data1<A> {} export type FreeV<F, A> = Return<A> | Suspend<F, A>; export type Free<F, A> = HKT2<IsFree, F, A>; export function inj<F, A>(f: FreeV<F, A>): Free<F, A> { return ((f: any): Free<F, A>) } export function prj<F, A>(fa: Free<F, A>): FreeV<F, A> { return ((fa: any): FreeV<F, A>) } export function of<F, A>(a: A): Free<F, A> { return inj(new Return(a)) } export function suspend<F, A>(ffa: HKT<F, Free<F, A>>): Free<F, A> { return inj(new Suspend(ffa)) } export function liftFree<F, A>(functor: Functor<F>, fa: HKT<F, A>): Free<F, A> { return suspend(functor.map(of, fa)) } export function foldFree<F, A>(functor: Functor<F>, join: (fa: HKT<F, A>) => A, ffa: Free<F, A>): A { const fa = prj(ffa) if (fa instanceof Return) { return fa.value0 } return join(functor.map(x => foldFree(functor, join, x), fa.value0)) } export function freeMonad<F>(functor: Functor<F>): Monad<HKT<IsFree, F>> { function map<A, B>(f: (a: A) => B, fa: Free<F, A>): Free<F, B> { const a = prj(fa) if (a instanceof Return) { return of(f(a.value0)) } return suspend(functor.map(x => map(f, x), a.value0)) } function ap<A, B>(fab: Free<F, (a: A) => B>, fa: Free<F, A>): Free<F, B> { return chain(f => map(f, fa), fab) // <= derived } function join<A>(ffa: Free<F, Free<F, A>>): Free<F, A> { const fa = prj(ffa) if (fa instanceof Return) { return fa.value0 } return suspend(functor.map(join, fa.value0)) } function chain<A, B>(f: (a: A) => Free<F, B>, fa: Free<F, A>): Free<F, B> { return join(map(f, fa)) // <= derived } return { map, ap, of, chain } }