// ets_tracing: off
/* adapted from https://github.com/gcanti/fp-ts */
import * as Tp from "../Collections/Immutable/Tuple/index.js"
import type { Either } from "../Either/core.js"
import type { Lazy, Predicate, Refinement } from "../Function/core.js"
import { identity } from "../Function/core.js"
import * as St from "../Structural/index.js"
import type { HasUnify } from "../Utils/index.js"
const _noneHash = St.hashString("@effect-ts/system/Option/None")
const _someHash = St.hashString("@effect-ts/system/Option/Some")
/**
* Definitions
*/
export class None implements HasUnify {
readonly _tag = "None";
[St.equalsSym](that: unknown): boolean {
return that instanceof None
}
get [St.hashSym](): number {
return _noneHash
}
}
export class Some implements HasUnify {
readonly _tag = "Some"
constructor(readonly value: A) {}
[St.equalsSym](that: unknown): boolean {
return that instanceof Some && St.equals(this.value, that.value)
}
get [St.hashSym](): number {
return St.combineHash(_someHash, St.hash(this.value))
}
}
export type Option = None | Some
/**
* Constructs none
*/
export const none: Option = new None()
/**
* Constructs none
*/
export function emptyOf(): Option {
return none
}
/**
* Constructs Some(A)
*/
export function some(a: A): Option {
return new Some(a)
}
/**
* Classic applicative
*/
export function ap_(fab: Option<(a: A) => B>, fa: Option): Option {
return isNone(fab) ? none : isNone(fa) ? none : some(fab.value(fa.value))
}
/**
* Classic applicative
*
* @ets_data_first ap_
*/
export function ap(fa: Option) {
return (fab: Option<(a: A) => B>): Option => ap_(fab, fa)
}
/**
* Zips `Option[A]` and `Option[B]` into `Option[(A, B)]`
*/
export function zip_(fa: Option, fb: Option): Option> {
return chain_(fa, (a) => map_(fb, (b) => Tp.tuple(a, b)))
}
/**
* Zips `Option[A]` and `Option[B]` into `Option[(A, B)]`
*
* @ets_data_first zip_
*/
export function zip(fb: Option) {
return (fa: Option): Option> => zip_(fa, fb)
}
/**
* Apply both and return first
*
* @ets_data_first zipFirst_
*/
export function zipFirst(fb: Option) {
return (fa: Option): Option => zipFirst_(fa, fb)
}
/**
* Apply both and return first
*/
export function zipFirst_(fa: Option, fb: Option): Option {
return ap_(
map_(fa, (a) => () => a),
fb
)
}
/**
* Apply both and return second
*
* @ets_data_first zipSecond_
*/
export function zipSecond(fb: Option) {
return (fa: Option): Option => zipSecond_(fa, fb)
}
/**
* Apply both and return second
*/
export function zipSecond_(fa: Option, fb: Option): Option {
return ap_(
map_(fa, () => (b: B) => b),
fb
)
}
/**
* Builds a new option constructed using the value of self
*/
export function chain_(self: Option, f: (a: A) => Option): Option {
return isNone(self) ? none : f(self.value)
}
/**
* Builds a new option constructed using the value of self
*
* @ets_data_first chain_
*/
export function chain(f: (a: A) => Option) {
return (self: Option): Option => chain_(self, f)
}
/**
* Like chain but ignores the constructed outout
*
* @ets_data_first tap_
*/
export function tap(f: (a: A) => Option) {
return (ma: Option): Option => chain_(ma, (a) => map_(f(a), () => a))
}
/**
* Like chain but ignores the constructed outout
*/
export function tap_(ma: Option, f: (a: A) => Option): Option {
return chain_(ma, (a) => map_(f(a), () => a))
}
/**
* Flattens nested options
*/
export function flatten(fa: Option