/**
* @since 1.0.0
*/
import type * as Data from "@effect/data/Data"
import type { Either } from "@effect/data/Either"
import * as Equal from "@effect/data/Equal"
import * as Equivalence from "@effect/data/Equivalence"
import type { LazyArg } from "@effect/data/Function"
import { constNull, constUndefined, dual, identity } from "@effect/data/Function"
import type { TypeLambda } from "@effect/data/HKT"
import type { Inspectable } from "@effect/data/Inspectable"
import * as either from "@effect/data/internal/Either"
import * as option from "@effect/data/internal/Option"
import * as N from "@effect/data/Number"
import type { Order } from "@effect/data/Order"
import * as order from "@effect/data/Order"
import type { Pipeable } from "@effect/data/Pipeable"
import type { Predicate, Refinement } from "@effect/data/Predicate"
import type * as Unify from "@effect/data/Unify"
import * as Gen from "@effect/data/UtilsGen"
/**
* @category models
* @since 1.0.0
*/
export type Option = None | Some
/**
* @category symbols
* @since 1.0.0
*/
export const TypeId = Symbol.for("@effect/data/Option")
/**
* @category symbols
* @since 1.0.0
*/
export type TypeId = typeof TypeId
/**
* @category models
* @since 1.0.0
*/
export interface None extends Data.Case, Pipeable, Inspectable {
readonly _tag: "None"
readonly [TypeId]: {
readonly _A: (_: never) => A
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: OptionUnify
[Unify.blacklistSymbol]?: OptionUnifyBlacklist
}
/**
* @category models
* @since 1.0.0
*/
export interface Some extends Data.Case, Pipeable, Inspectable {
readonly _tag: "Some"
readonly value: A
readonly [TypeId]: {
readonly _A: (_: never) => A
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: OptionUnify
[Unify.blacklistSymbol]?: OptionUnifyBlacklist
}
/**
* @category models
* @since 1.0.0
*/
export interface OptionUnify {
Option?: () => A[Unify.typeSymbol] extends Option | infer _ ? Option : never
}
/**
* @category models
* @since 1.0.0
*/
export interface OptionUnifyBlacklist {}
/**
* @category type lambdas
* @since 1.0.0
*/
export interface OptionTypeLambda extends TypeLambda {
readonly type: Option
}
/**
* Creates a new `Option` that represents the absence of a value.
*
* @category constructors
* @since 1.0.0
*/
export const none = (): Option => option.none
/**
* Creates a new `Option` that wraps the given value.
*
* @param value - The value to wrap.
*
* @category constructors
* @since 1.0.0
*/
export const some: (value: A) => Option = option.some
/**
* Tests if a value is a `Option`.
*
* @param input - The value to check.
*
* @example
* import { some, none, isOption } from '@effect/data/Option'
*
* assert.deepStrictEqual(isOption(some(1)), true)
* assert.deepStrictEqual(isOption(none()), true)
* assert.deepStrictEqual(isOption({}), false)
*
* @category guards
* @since 1.0.0
*/
export const isOption: (input: unknown) => input is Option = option.isOption
/**
* Determine if a `Option` is a `None`.
*
* @param self - The `Option` to check.
*
* @example
* import { some, none, isNone } from '@effect/data/Option'
*
* assert.deepStrictEqual(isNone(some(1)), false)
* assert.deepStrictEqual(isNone(none()), true)
*
* @category guards
* @since 1.0.0
*/
export const isNone: (self: Option) => self is None = option.isNone
/**
* Determine if a `Option` is a `Some`.
*
* @param self - The `Option` to check.
*
* @example
* import { some, none, isSome } from '@effect/data/Option'
*
* assert.deepStrictEqual(isSome(some(1)), true)
* assert.deepStrictEqual(isSome(none()), false)
*
* @category guards
* @since 1.0.0
*/
export const isSome: (self: Option) => self is Some = option.isSome
/**
* Matches the given `Option` and returns either the provided `onNone` value or the result of the provided `onSome`
* function when passed the `Option`'s value.
*
* @param self - The `Option` to match
* @param onNone - The value to be returned if the `Option` is `None`
* @param onSome - The function to be called if the `Option` is `Some`, it will be passed the `Option`'s value and its result will be returned
*
* @example
* import { some, none, match } from '@effect/data/Option'
* import { pipe } from "@effect/data/Function"
*
* assert.deepStrictEqual(
* pipe(some(1), match({ onNone: () => 'a none', onSome: (a) => `a some containing ${a}` })),
* 'a some containing 1'
* )
*
* assert.deepStrictEqual(
* pipe(none(), match({ onNone: () => 'a none', onSome: (a) => `a some containing ${a}` })),
* 'a none'
* )
*
* @category pattern matching
* @since 1.0.0
*/
export const match: {
(options: {
readonly onNone: LazyArg
readonly onSome: (a: A) => C
}): (self: Option) => B | C
(self: Option, options: {
readonly onNone: LazyArg
readonly onSome: (a: A) => C
}): B | C
} = dual(
2,
(self: Option, { onNone, onSome }: {
readonly onNone: LazyArg
readonly onSome: (a: A) => C
}): B | C => isNone(self) ? onNone() : onSome(self.value)
)
/**
* Returns a type guard from a `Option` returning function.
* This function ensures that a type guard definition is type-safe.
*
* @example
* import * as O from "@effect/data/Option"
*
* const parsePositive = (n: number): O.Option =>
* n > 0 ? O.some(n) : O.none()
*
* const isPositive = O.toRefinement(parsePositive)
*
* assert.deepStrictEqual(isPositive(1), true)
* assert.deepStrictEqual(isPositive(-1), false)
*
* @category conversions
* @since 1.0.0
*/
export const toRefinement = (f: (a: A) => Option): (a: A) => a is B => (a: A): a is B => isSome(f(a))
/**
* Converts an `Iterable` of values into an `Option`. Returns the first value of the `Iterable` wrapped in a `Some`
* if the `Iterable` is not empty, otherwise returns `None`.
*
* @param collection - The `Iterable` to be converted to an `Option`.
*
* @example
* import { fromIterable, some, none } from '@effect/data/Option'
*
* assert.deepStrictEqual(fromIterable([1, 2, 3]), some(1))
* assert.deepStrictEqual(fromIterable([]), none())
*
* @category conversions
* @since 1.0.0
*/
export const fromIterable = (collection: Iterable): Option => {
for (const a of collection) {
return some(a)
}
return none()
}
/**
* Converts a `Either` to an `Option` discarding the error.
*
* Alias of {@link fromEither}.
*
* @example
* import * as O from "@effect/data/Option"
* import * as E from "@effect/data/Either"
*
* assert.deepStrictEqual(O.getRight(E.right('ok')), O.some('ok'))
* assert.deepStrictEqual(O.getRight(E.left('err')), O.none())
*
* @category conversions
* @since 1.0.0
*/
export const getRight: (self: Either) => Option = either.getRight
/**
* Converts a `Either` to an `Option` discarding the value.
*
* @example
* import * as O from "@effect/data/Option"
* import * as E from "@effect/data/Either"
*
* assert.deepStrictEqual(O.getLeft(E.right("ok")), O.none())
* assert.deepStrictEqual(O.getLeft(E.left("a")), O.some("a"))
*
* @category conversions
* @since 1.0.0
*/
export const getLeft: (self: Either) => Option = either.getLeft
/**
* Returns the value of the `Option` if it is `Some`, otherwise returns `onNone`
*
* @param self - The `Option` to get the value of.
* @param onNone - Function that returns the default value to return if the `Option` is `None`.
*
* @example
* import { some, none, getOrElse } from '@effect/data/Option'
* import { pipe } from "@effect/data/Function"
*
* assert.deepStrictEqual(pipe(some(1), getOrElse(() => 0)), 1)
* assert.deepStrictEqual(pipe(none(), getOrElse(() => 0)), 0)
*
* @category getters
* @since 1.0.0
*/
export const getOrElse: {
(onNone: LazyArg): (self: Option) => B | A
(self: Option, onNone: LazyArg): A | B
} = dual(
2,
(self: Option, onNone: LazyArg): A | B => isNone(self) ? onNone() : self.value
)
/**
* Returns the provided `Option` `that` if `self` is `None`, otherwise returns `self`.
*
* @param self - The first `Option` to be checked.
* @param that - The `Option` to return if `self` is `None`.
*
* @example
* import * as O from "@effect/data/Option"
* import { pipe } from "@effect/data/Function"
*
* assert.deepStrictEqual(
* pipe(
* O.none(),
* O.orElse(() => O.none())
* ),
* O.none()
* )
* assert.deepStrictEqual(
* pipe(
* O.some('a'),
* O.orElse(() => O.none())
* ),
* O.some('a')
* )
* assert.deepStrictEqual(
* pipe(
* O.none(),
* O.orElse(() => O.some('b'))
* ),
* O.some('b')
* )
* assert.deepStrictEqual(
* pipe(
* O.some('a'),
* O.orElse(() => O.some('b'))
* ),
* O.some('a')
* )
*
* @category error handling
* @since 1.0.0
*/
export const orElse: {
(that: LazyArg