import { Either, fold, isLeft, isRight, right } from 'fp-ts/lib/Either' import { Ord } from 'fp-ts/lib/Ord' import { pipe } from 'fp-ts/lib/pipeable' import { isNil } from '@monorail/sharedHelpers/typeGuards' export * from 'fp-ts/lib/Either' /** * type guard for Either */ export const isEither = (x: unknown): x is Either => { if (!isNil(x)) { const x_ = x as { left?: unknown right?: unknown _tag?: unknown } return ( !isNil(x_.right) || (!isNil(x_.left) && ((!isNil(x_._tag) && x_._tag === 'Left') || x_._tag === 'Right')) ) } return false } /** * Derives an `Ord` instance for `Either` given an `Ord` and an * `Ord`. */ export const getOrd = ( ordA: Ord, ordB: Ord, ): Ord> => ({ equals: (x, y) => isLeft(x) && isLeft(y) ? ordA.equals(x.left, y.left) : isRight(x) && isRight(y) ? ordB.equals(x.right, y.right) : false, compare: (x, y) => isLeft(x) && isLeft(y) ? ordA.compare(x.left, y.left) : isRight(x) && isRight(y) ? ordB.compare(x.right, y.right) : isLeft(x) && isRight(y) ? -1 : 1, }) export const orElseW = (f: (a: E) => Either) => ( ma: Either, ): Either => pipe(ma, fold>(f, right)) export const toUnion = (either: Either): E | A => pipe( either, fold( (e: E): E | A => e, (a: A): E | A => a, ), )