@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">
120 lines (101 loc) • 3.14 kB
Flow
// @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, B> = A; // eslint-disable-line no-unused-vars
export type Const<A, B> = HKT2<IsConst, A, B>;
export type ConstF = HKT<IsConst, *>;
export function inj<A, B>(a: ConstV<A, B>): Const<A, B> {
return ((a: any): Const<A, B>)
}
export function prj<A, B>(a: Const<A, B>): ConstV<A, B> {
return ((a: any): ConstV<A, B>)
}
export function compose<A, B, C>(x: Const<B, C>, y: Const<A, B>): Const<A, C> {
return ((y: any): Const<A, C>)
}
export function map<A, B, C>(f: (a: A) => B, fa: Const<C, A>): Const<C, B> {
return ((fa: any): Const<C, B>)
}
export function contramap<A, B, C>(f: (b: B) => A, fa: Const<C, A>): Const<C, B> {
return ((fa: any): Const<C, B>)
}
export function getSetoid<A, B>(setoid: Setoid<A>): Setoid<Const<A, B>> {
return {
equals(x: Const<A, B>, y: Const<A, B>): boolean {
return setoid.equals(prj(x), prj(y))
}
}
}
export function getSemigroup<A, B>(semigroup: Semigroup<A>): Semigroup<Const<A, B>> {
return {
concat(x: Const<A, B>, y: Const<A, B>): Const<A, B> {
return inj(semigroup.concat(prj(x), prj(y)))
}
}
}
export function getMonoid<A, B>(monoid: Monoid<A>): Monoid<Const<A, B>> {
const { concat } = getSemigroup(monoid)
const empty: Const<A, any> = inj(monoid.empty())
return {
concat,
empty<B>(): Const<A, B> {
return empty
}
}
}
export function getApply<C>(semigroup: Semigroup<C>): Apply<HKT<IsConst, C>> {
return {
map,
ap<A, B>(fab: Const<C, (a: A) => B>, fa: Const<C, A>): Const<C, B> {
const x = prj(fab)
const y = prj(fa)
return inj(semigroup.concat(x, y))
}
}
}
export function getApplicative<A>(monoid: Monoid<A>): Applicative<HKT<IsConst, A>> {
const { map, ap } = getApply(monoid)
return {
map,
ap,
of<B>(b: B): Const<A, B> { // eslint-disable-line no-unused-vars
return inj(monoid.empty())
}
}
}
export function getChain<C>(semigroup: Semigroup<C>): Chain<HKT<IsConst, C>> {
const { map, ap } = getApply(semigroup)
return {
map,
ap,
chain<A, B>(f: (a: A) => Const<C, B>, fa: Const<C, A>): Const<C, B> {
return ((fa: any): Const<C, B>)
}
}
}
if (false) { // eslint-disable-line
({
compose,
map,
contramap
}: Functor<ConstF> &
Contravariant<ConstF> &
Semigroupoid<IsConst>)
}