import type { FunctionN, Lazy, Predicate, Refinement } from "../Function"; import type { Option } from "../Option"; import type { Either } from "./model"; /* * ------------------------------------------- * Either Constructors * ------------------------------------------- */ /** * ```haskell * left :: e -> Left e * ``` * * Constructs a new `Either` holding a `Left` value. This usually represents a failure, due to the right-bias of this structure * * @category Constructors * @since 1.0.0 */ export const left = (e: E): Either => ({ _tag: "Left", left: e }); /** * ```haskell * right :: a -> Right a * ``` * * Constructs a new `Either` holding a `Right` value. This usually represents a successful value due to the right bias of this structure * * @category Constructors * @since 1.0.0 */ export const right = (a: A): Either => ({ _tag: "Right", right: a }); /** * * ```haskell * fromNullable :: (() -> e) -> ?a -> Either e a * ``` * Takes a default and a nullable value, if the value is not nully, turn it into a `Right`, if the value is nully use the provided default as a `Left` * * @category Constructors * @since 1.0.0 */ export const fromNullable = (e: Lazy) => (a: A): Either> => a == null ? left(e()) : right(a as NonNullable); /** * ```haskell * _partial :: (() -> a, (* -> e)) -> Either e a * ``` * * Constructs a new `Either` from a function that might throw * * @category Constructors * @since 1.0.0 */ export const partial_ = (a: Lazy, onThrow: (reason: unknown) => E): Either => { try { return right(a()); } catch (e) { return left(onThrow(e)); } }; /** * ```haskell * partial :: (* -> e) -> (() -> a) -> Either e a * ``` * * Constructs a new `Either` from a function that might throw * * @category Constructors * @since 1.0.0 */ export const partial = (onError: (reason: unknown) => E) => (a: Lazy): Either => { try { return right(a()); } catch (e) { return left(onError(e)); } }; /** * ```haskell * _partialK :: (((a, b, ...) -> c), (* -> e)) -> ((a, b, ...) -> Either e c) * ``` * * @category Constructors * @since 1.0.0 */ export const partialK_ = , B, E>( f: FunctionN, onThrow: (reason: unknown) => E ): ((...args: A) => Either) => (...a) => partial_(() => f(...a), onThrow); /** * ```haskell * partialK :: (* -> e) -> ((a, b, ...) -> c) -> ((a, b, ...) -> Either e c) * ``` * * @category Constructors * @since 1.0.0 */ export const partialK = (onThrow: (reason: unknown) => E) => , B>( f: FunctionN ) => partialK_(f, onThrow); export type Json = boolean | number | string | null | JsonArray | JsonRecord; export interface JsonRecord extends Readonly> {} export interface JsonArray extends ReadonlyArray {} /** * ```haskell * _parseJSON :: (String, (* -> e)) -> Either e Json * ``` * * Converts a JavaScript Object Notation (JSON) string into an object. * * @category Constructors * @since 1.0.0 */ export const parseJson_ = (s: string, onThrow: (reason: unknown) => E): Either => partial_(() => JSON.parse(s), onThrow); /** * ```haskell * parseJSON :: (* -> e) -> String -> Either e Json * ``` * * Converts a JavaScript Object Notation (JSON) string into an object. * * @category Constructors * @since 1.0.0 */ export const parseJson = (onThrow: (reason: unknown) => E) => (s: string): Either => parseJson_(s, onThrow); /** * ```haskell * _stringifyJSON :: (*, (* -> E)) -> Either e String * ``` * * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * * @category Constructors * @since 1.0.0 */ export const stringifyJson_ = (u: unknown, onThrow: (reason: unknown) => E): Either => partial_(() => JSON.stringify(u), onThrow); /** * ```haskell * stringifyJSON :: (* -> E) -> * -> Either e String * ``` * * Converts a JavaScript value to a JavaScript Object Notation (JSON) string. * * @category Constructors * @since 1.0.0 */ export const stringifyJSON = (onThrow: (reason: unknown) => E) => (u: unknown): Either => stringifyJson_(u, onThrow); /** * ```haskell * _fromMaybe :: (Maybe a, (() -> e)) -> Either e a * ``` * * @category Constructors * @since 1.0.0 */ export const fromOption_ = (fa: Option, onNothing: Lazy): Either => fa._tag === "None" ? left(onNothing()) : right(fa.value); /** * ```haskell * fromMaybe :: (() -> e) -> Maybe a -> Either e a * ``` * * @category Constructors * @since 1.0.0 */ export const fromOption: (onNothing: Lazy) => (fa: Option) => Either = (f) => (fa) => fromOption_(fa, f); /** * ```haskell * _fromPredicate :: (a, (a is b), (a -> e)) -> Either e b * _fromPredicate :: (a, (a -> Boolean), (a -> e)) -> Either e a * ``` * * @category Constructors * @since 1.0.0 */ export const fromPredicate_: { (a: A, refinement: Refinement, onFalse: (a: A) => E): Either; (a: A, predicate: Predicate, onFalse: (a: A) => E): Either; } = (a: A, predicate: Predicate, onFalse: (a: A) => E): Either => predicate(a) ? right(a) : left(onFalse(a)); /** * ```haskell * fromPredicate :: ((a is b), (a -> e)) -> a -> Either e b * fromPredicate :: ((a -> Boolean), (a -> e)) -> a -> Either e a * ``` * * @category Constructors * @since 1.0.0 */ export const fromPredicate: { (refinement: Refinement, onFalse: (a: A) => E): (a: A) => Either; (predicate: Predicate, onFalse: (a: A) => E): (a: A) => Either; } = (predicate: Predicate, onFalse: (a: A) => E) => (a: A) => fromPredicate_(a, predicate, onFalse);