import type { Applicative } from './Applicative' import type { Functor2, FunctorMin } from './Functor' import { flow, identity } from './function' import { Functor, getFunctorComposition } from './Functor' import * as HKT from './HKT' export interface Traversable extends Functor { readonly traverse_: TraverseFn_ readonly traverse: TraverseFn readonly sequence: SequenceFn } export type TraversableMin = FunctorMin & { readonly traverse_: TraverseFn_ } export function Traversable(F: TraversableMin): Traversable { const sequence: SequenceFn = (A) => { const traverseA_ = F.traverse_(A) return (ta) => traverseA_(ta, identity) } return HKT.instance>({ ...Functor(F), traverse_: F.traverse_, traverse: (A) => { const traverseA_ = F.traverse_(A) return (f) => (ta) => traverseA_(ta, f) }, sequence }) } export interface TraversableComposition extends Functor2 { readonly traverse_: TraverseFnComposition_ readonly traverse: TraverseFnComposition readonly sequence: SequenceFnComposition } export function getTraversableComposition( F: Traversable, G: Traversable ): TraversableComposition { const traverse_: TraversableComposition['traverse_'] = (H) => (tfga, f) => F.traverse_(H)(tfga, (tga) => G.traverse_(H)(tga, f)) return HKT.instance>({ ...getFunctorComposition(F, G), traverse_, traverse: (H) => flow(G.traverse(H), F.traverse(H)), sequence: (H) => flow(F.map(G.sequence(H)), F.sequence(H)) }) } export interface TraverseFn { (A: Applicative): ( f: (a: A) => HKT.Kind ) => ( ta: HKT.Kind ) => HKT.Kind> } export interface TraverseFn_ { (A: Applicative): < FN extends string, FK, FQ, FW, FX, FI, FS, FR, FE, GN extends string, GK, GQ, GW, GX, GI, GS, GR, GE, A, B >( ta: HKT.Kind, f: (a: A) => HKT.Kind ) => HKT.Kind> } export interface TraverseFnComposition { (A: Applicative): ( f: (a: A) => HKT.Kind ) => ( fga: HKT.Kind> ) => HKT.Kind< H, CH, HN, HK, HQ, HW, HX, HI, HS, HR, HE, HKT.Kind> > } export interface TraverseFnComposition_ { (A: Applicative): < FN extends string, FK, FQ, FW, FX, FI, FS, FR, FE, GN extends string, GK, GQ, GW, GX, GI, GS, GR, GE, HN extends string, HK, HQ, HW, HX, HI, HS, HR, HE, A, B >( fga: HKT.Kind>, f: (a: A) => HKT.Kind ) => HKT.Kind< H, CH, HN, HK, HQ, HW, HX, HI, HS, HR, HE, HKT.Kind> > } export function implementTraverse_(): ( i: (_: { A: A B: B G: G N: N K: K Q: Q W: W X: X I: I S: S R: R E: E }) => ( G: Applicative> ) => ( ta: HKT.Kind, f: (a: A) => HKT.HKT ) => HKT.HKT> ) => TraverseFn_ export function implementTraverse_() { return (i: any) => i() } export function implementTraverse(): ( i: (_: { A: A B: B G: G N: N K: K Q: Q W: W X: X I: I S: S R: R E: E }) => ( G: Applicative> ) => ( f: (a: A) => HKT.HKT ) => (ta: HKT.Kind) => HKT.HKT> ) => TraverseFn export function implementTraverse() { return (i: any) => i() } export interface SequenceFn { (A: Applicative): < NF extends string, KF, QF, WF, XF, IF, SF, RF, EF, NG extends string, KG, QG, WG, XG, IG, SG, RG, EG, A >( ta: HKT.Kind> ) => HKT.Kind> } export interface SequenceFnComposition { (A: Applicative): < NF extends string, KF, QF, WF, XF, IF, SF, RF, EF, NG extends string, KG, QG, WG, XG, IG, SG, RG, EG, NH extends string, KH, QH, WH, XH, IH, SH, RH, EH, A >( fgha: HKT.Kind< F, CF, NF, KF, QF, WF, XF, IF, SF, RF, EF, HKT.Kind> > ) => HKT.Kind< H, CH, NH, KH, QH, WH, XH, IH, SH, RH, EH, HKT.Kind> > } export function implementSequence(): ( i: (_: { A: A B: B G: G N: N K: K Q: Q W: W X: X I: I S: S R: R E: E }) => ( G: Applicative> ) => ( ta: HKT.Kind> ) => HKT.HKT> ) => SequenceFn export function implementSequence() { return (i: any) => i() }