// ets_tracing: off import * as E from "@effect-ts/system/Either" import { constant, identity, pipe } from "../../Function/index.js" import * as HKT from "../../Prelude/HKT/index.js" import type { Any } from "../Any/index.js" import type { Applicative } from "../Applicative/index.js" import type { Covariant } from "../Covariant/index.js" import { chainF, succeedF } from "../DSL/index.js" import type { Monad } from "../Monad/index.js" export interface Select extends HKT.Base { readonly _Select: "Select" readonly select: ( fab: HKT.Kind B> ) => ( fa: HKT.Kind< F, C, HKT.Intro, HKT.Intro, HKT.Intro, HKT.Intro, HKT.Intro, HKT.Intro, HKT.Intro, HKT.Intro, E.Either > ) => HKT.Kind< F, C, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, B | B2 > } export type Selective = Select & Covariant & Any export type SelectiveMonad = Selective & Monad export function monad( F: Monad ): SelectiveMonad export function monad(F: Monad>): SelectiveMonad, HKT.Auto> { return HKT.instance>>({ ...F, select: (fab: HKT.HKT B>) => (fa: HKT.HKT>): HKT.HKT => pipe( fa, chainF(F)( E.fold( (a) => pipe( fab, F.map((g) => g(a) as B | B2) ), (b) => succeedF(F)(b as B | B2) ) ) ) }) } export function applicative( F: Applicative ): SelectiveMonad export function applicative( F: Applicative> ): Selective, HKT.Auto> { return HKT.instance>>({ ...F, select: (fab: HKT.HKT B>) => (fa: HKT.HKT>): HKT.HKT => pipe( fa, F.both(fab), F.map(({ tuple: [ea, f] }) => E.fold_(ea, f, identity)) ) }) } export function branchF( F: Selective ): ( lhs: HKT.Kind D1>, rhs: HKT.Kind D2> ) => ( fe: HKT.Kind> ) => HKT.Kind< F, C, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, D1 | D2 > export function branchF(F: Selective>) { return ( lhs: HKT.HKT C>, rhs: HKT.HKT D> ): ((fe: HKT.HKT>) => HKT.HKT) => (x) => pipe( x, F.map(E.map(E.left)), F.select( pipe( lhs, F.map((fac) => (x) => pipe(x, fac, E.right, E.widenE())) ) ), F.select(rhs) ) } export function ifF( F: Selective ): ( then_: HKT.Kind, else_: HKT.Kind ) => ( if_: HKT.Kind ) => HKT.Kind< F, C, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, A | B > export function ifF(F: Selective>) { return ( then_: HKT.HKT, else_: HKT.HKT ): ((if_: HKT.HKT) => HKT.HKT) => (x) => pipe( x, F.map((x) => (x ? E.left(undefined) : E.right(undefined))), branchF(F)(pipe(then_, F.map(constant)), pipe(else_, F.map(constant))) ) } export function whenF( F: Selective ): ( act: HKT.Kind ) => ( if_: HKT.Kind ) => HKT.Kind< F, C, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, HKT.Mix, void > export function whenF(F: Selective>) { return (act: HKT.HKT): ((if_: HKT.HKT) => HKT.HKT) => ifF(F)(act, succeedF(F)(undefined)) }