import type * as P from "@principia/prelude"; import * as HKT from "@principia/prelude/HKT"; import { left, right } from "./constructors"; import { map, map_ } from "./functor"; import { isLeft } from "./guards"; import type { Either, URI, V } from "./model"; /* * ------------------------------------------- * Bifunctor Either * ------------------------------------------- */ /** * ```haskell * swap :: Bifunctor p => p a b -> p b a * ``` * * Swaps the positions of a Bifunctor's arguments * * @category AltBifunctor * @since 1.0.0 */ export const swap = (pab: Either): Either => (isLeft(pab) ? right(pab.left) : left(pab.right)); /** * ```haskell * bimap_ :: Bifunctor p => (p a b, (a -> c), (b -> d)) -> p c d * ``` * * Map a pair of functions over the two type arguments of the bifunctor. * * @category Bifunctor * @since 1.0.0 */ export const bimap_ = (pab: Either, f: (e: E) => G, g: (a: A) => B): Either => isLeft(pab) ? left(f(pab.left)) : right(g(pab.right)); /** * ```haskell * bimap :: Bifunctor p => ((a -> c), (b -> d)) -> p a b -> p c d * ``` * * Map a pair of functions over the two type arguments of the bifunctor. * * @category Bifunctor * @since 1.0.0 */ export const bimap = (f: (e: E) => G, g: (a: A) => B) => (pab: Either): Either => bimap_(pab, f, g); /** * ```haskell * first_ :: Bifunctor p => (p a c, (a -> b)) -> p b c * ``` * * Map a function over the first type argument of a bifunctor. * * @category Bifunctor * @since 1.0.0 */ export const first_ = (pab: Either, f: (e: E) => G): Either => isLeft(pab) ? left(f(pab.left)) : pab; /** * ```haskell * first :: Bifunctor p => (a -> c) -> p a b -> p c b * ``` * * Map a function over the first type argument of a bifunctor. * * @category Bifunctor * @since 1.0.0 */ export const first = (f: (e: E) => G) => (pab: Either): Either => first_(pab, f); /** * ```haskell * mapLeft_ :: Bifunctor p => (p a c, (a -> b)) -> p b c * ``` * * Map a function over the first type argument of a bifunctor. * * @category Bifunctor * @since 1.0.0 */ export const mapLeft_ = first_; /** * ```haskell * mapLeft :: Bifunctor p => (a -> c) -> p a b -> p c b * ``` * * Map a function over the first type argument of a bifunctor. * * @category Bifunctor * @since 1.0.0 */ export const mapLeft = first; /** * @category Instances * @since 1.0.0 */ export const Bifunctor: P.Bifunctor<[URI], V> = HKT.instance({ bimap_, bimap, first_, first, second_: map_, second: map }); /** * @category Instances * @since 1.0.0 */ export const Bifunctor2: P.Bifunctor2 = HKT.instance({ bimap_, bimap, first_, first, second_: map_, second: map });