// ets_tracing: off import type { Base, Infer, Kind, URIS } from "../HKT/index.js" type KindFromObj = Kind< URI, C, Infer, Infer, Infer, Infer, Infer, Infer, Infer, Infer, Infer > export interface MatchFn { < X extends { [tag in N]: string }, K extends { [k in X[N]]: ( _: Extract, __: Extract ) => Kind } >( matcher: K ): (_: X) => KindFromObj }[keyof K]> < X extends { [tag in N]: string }, K extends Partial<{ [k in X[N]]: ( _: Extract, __: Extract ) => Kind }>, Ret extends Kind >( matcher: K, def: ( _: Exclude, __: Exclude ) => Ret ): (_: X) => KindFromObj< URI, C, | { [k in keyof K]: K[k] extends (...args: any) => any ? ReturnType : never }[keyof K] | Ret > } export interface MatchInFn { (): { < K extends { [k in X[N]]: ( _: Extract, __: Extract ) => Kind } >( matcher: K ): (_: X) => KindFromObj }[keyof K]> < K extends Partial<{ [k in X[N]]: ( _: Extract, __: Extract ) => Kind }>, Ret extends Kind >( matcher: K, def: ( _: Exclude, __: Exclude ) => Ret ): (_: X) => KindFromObj< URI, C, | { [k in keyof K]: K[k] extends (...args: any) => any ? ReturnType : never }[keyof K] | Ret > } } export interface MatchMorphFn< URI extends URIS, C, N extends string, X extends { [tag in N]: string } > { < K extends { [k in X[N]]: ( _: Extract, __: Extract ) => Kind } >( matcher: K ): (_: X) => KindFromObj }[keyof K]> < X extends { [tag in N]: string }, K extends Partial<{ [k in X[N]]: ( _: Extract, __: Extract ) => Kind }>, Ret extends Kind >( matcher: K, def: ( _: Exclude, __: Exclude ) => Ret ): (_: X) => KindFromObj< URI, C, | { [k in keyof K]: K[k] extends (...args: any) => any ? ReturnType : never }[keyof K] | Ret > } export function matchers(_: Base) { function match(tag: N): MatchFn { return (...args: any[]) => { return (_: any) => { const matcher = args[0][_[tag]] return matcher ? matcher(_, _) : args[1](_, _) } } } function matchIn(tag: N): MatchInFn { return () => (...args: any[]) => { return (_: any) => { const matcher = args[0][_[tag]] return matcher ? matcher(_, _) : args[1](_, _) } } } function matchMorph(MorphADT: { tag: N _A: X }): MatchMorphFn { return (...args: any[]) => { return (_: any) => { const matcher = args[0][_[MorphADT.tag]] return matcher ? matcher(_, _) : args[1](_, _) } } } const matchTagIn = matchIn("_tag") const matchTag = match("_tag") return { match, matchTag, matchIn, matchTagIn, matchMorph } }