/** * @since 0.24.0 */ import * as Either from "effect/Either" import { dual } from "effect/Function" import type { Kind, TypeLambda } from "effect/HKT" import type * as applicative from "../Applicative.js" import type * as bicovariant from "../Bicovariant.js" import type * as chainable from "../Chainable.js" import * as covariant from "../Covariant.js" import type * as flatMap_ from "../FlatMap.js" import type * as foldable from "../Foldable.js" import type * as invariant from "../Invariant.js" import type * as monad from "../Monad.js" import type * as of_ from "../Of.js" import type * as pointed from "../Pointed.js" import type * as product_ from "../Product.js" import type * as semiAlternative from "../SemiAlternative.js" import type * as semiApplicative from "../SemiApplicative.js" import type * as semiCoproduct from "../SemiCoproduct.js" import type * as semiProduct from "../SemiProduct.js" import type * as traversable from "../Traversable.js" const of = Either.right const map = Either.map const imap = covariant.imap(map) const bimap: { ( onLeft: (e: E1) => E2, onRight: (a: A) => B ): (self: Either.Either) => Either.Either ( self: Either.Either, onLeft: (e: E1) => E2, onRight: (a: A) => B ): Either.Either } = dual( 3, ( self: Either.Either, onLeft: (e: E1) => E2, onRight: (a: A) => B ): Either.Either => Either.mapBoth(self, { onLeft, onRight }) ) const flatMap = Either.flatMap const product = ( self: Either.Either, that: Either.Either ): Either.Either<[A, B], E1 | E2> => Either.isRight(self) ? (Either.isRight(that) ? Either.right([self.right, that.right]) : Either.left(that.left)) : Either.left(self.left) const productMany = ( self: Either.Either, collection: Iterable> ): Either.Either<[A, ...Array], E> => { if (Either.isLeft(self)) { return Either.left(self.left) } const out: [A, ...Array] = [self.right] for (const e of collection) { if (Either.isLeft(e)) { return Either.left(e.left) } out.push(e.right) } return Either.right(out) } const productAll = ( collection: Iterable> ): Either.Either, E> => { const out: Array = [] for (const e of collection) { if (Either.isLeft(e)) { return Either.left(e.left) } out.push(e.right) } return Either.right(out) } const coproduct = ( self: Either.Either, that: Either.Either ): Either.Either => Either.isRight(self) ? self : that const coproductMany = ( self: Either.Either, collection: Iterable> ): Either.Either => { let out = self if (Either.isRight(out)) { return out } for (out of collection) { if (Either.isRight(out)) { return out } } return out } const traverse = ( F: applicative.Applicative ): { ( f: (a: A) => Kind ): (self: Either.Either) => Kind> ( self: Either.Either, f: (a: A) => Kind ): Kind> } => dual(2, ( self: Either.Either, f: (a: A) => Kind ): Kind> => Either.isLeft(self) ? F.of>(Either.left(self.left)) : F.map>(f(self.right), Either.right)) /** * @category instances * @since 0.24.0 */ export const Bicovariant: bicovariant.Bicovariant = { bimap } /** * @category instances * @since 0.24.0 */ export const Covariant: covariant.Covariant = { imap, map } /** * @category instances * @since 0.24.0 */ export const Invariant: invariant.Invariant = { imap } /** * @category instances * @since 0.24.0 */ export const Of: of_.Of = { of } /** * @category instances * @since 0.24.0 */ export const Pointed: pointed.Pointed = { of, imap, map } /** * @category instances * @since 0.24.0 */ export const FlatMap: flatMap_.FlatMap = { flatMap } /** * @category instances * @since 0.24.0 */ export const Chainable: chainable.Chainable = { imap, map, flatMap } /** * @category instances * @since 0.24.0 */ export const Monad: monad.Monad = { imap, of, map, flatMap } /** * @category instances * @since 0.24.0 */ export const SemiProduct: semiProduct.SemiProduct = { imap, product, productMany } /** * @category instances * @since 0.24.0 */ export const Product: product_.Product = { of, imap, product, productMany, productAll } /** * @category instances * @since 0.24.0 */ export const SemiApplicative: semiApplicative.SemiApplicative = { imap, map, product, productMany } /** * @category instances * @since 0.24.0 */ export const Applicative: applicative.Applicative = { imap, of, map, product, productMany, productAll } /** * @category instances * @since 0.24.0 */ export const SemiCoproduct: semiCoproduct.SemiCoproduct = { imap, coproduct, coproductMany } /** * @category instances * @since 0.24.0 */ export const SemiAlternative: semiAlternative.SemiAlternative = { map, imap, coproduct, coproductMany } /** * @category instances * @since 0.24.0 */ export const Foldable: foldable.Foldable = { reduce: dual( 3, (self: Either.Either, b: B, f: (b: B, a: A) => B): B => Either.isLeft(self) ? b : f(b, self.right) ) } /** * @category instances * @since 0.24.0 */ export const Traversable: traversable.Traversable = { traverse }