import { datatype, $ } from '.'
import { Functor } from './functor'
import { ap, Apply } from './apply'
import { Cartesian } from './cartesian'
import { Applicative } from './applicative'
import { FlatMap } from './flatmap'
import { Monad } from './monad'
@datatype('Id')
export class Id {
value: A
constructor(value: A) {
this.value = value
}
valueOf() {
return this.value
}
}
export class IdFunctor implements Functor<"Id"> {
map(f: (a: A) => B, fb: $<"Id", A>): $<"Id", B> {
return new Id(f(fb.value))
}
}
declare module '.' {
interface _ {
"Id": Id
}
}
declare module './functor' {
namespace Functor {
export let Id: IdFunctor
}
}
Functor.Id = new IdFunctor
export class IdCartesian implements Cartesian<"Id"> {
product(fa: Id, fb: Id): Id<[A, B]> {
return new Id([fa.value, fb.value] as [A, B])
}
}
declare module './cartesian' {
namespace Cartesian {
export let Id: IdCartesian
}
}
Cartesian.Id = new IdCartesian
export class IdApply implements Apply<"Id"> {
ap(fab: Id<(a: A) => B>, fa: Id): Id {
return ap<"Id", A, B>(fab, fa)
}
map = Functor.Id.map
product = Cartesian.Id.product
}
declare module './apply' {
namespace Apply {
export let Id: IdApply
}
}
Apply.Id = new IdApply
export class IdApplicative extends IdApply implements Applicative<"Id">{
pure(a: A): Id {
return new Id(a)
}
}
declare module './applicative' {
namespace Applicative {
export let Id: IdApplicative
}
}
Applicative.Id = new IdApplicative
export class IdFlatMap extends IdApply implements FlatMap<"Id">{
flatMap(f: (a: A) => Id, fa: Id): Id {
return this.map(f, fa).value
}
}
declare module './flatmap' {
namespace FlatMap {
export let Id: IdFlatMap
}
}
FlatMap.Id = new IdFlatMap
export class IdMonad extends IdApplicative implements Monad<"Id">{
flatMap = FlatMap.Id.flatMap
}
declare module './monad' {
namespace Monad {
export let Id: IdMonad
}
}
Monad.Id = new IdMonad