Well-typed Maybe data structure
yarn add @typed/maybe
# or
npm install --save @typed/maybe
All functions are curried!
A JSON-serializable Just data-structure
export interface Just<A> {
readonly '@typed/Just': A
}
Creates a Just given a value.
See the code
export function of<A>(value: A): Just<A> {
return { '@typed/Just': value }
}
}
Creates a Maybe containing a value. If the value is undefined
or null
a Nothing
will be returned. All other values will be wrapped in a Just
.
See the code
export const of: <A>(value: A | void) => Maybe<A> = toMaybe
}
The Nothing type, used in place of nulls or undefined.
export interface Nothing {
readonly '@typed/Nothing': true
}
export const Nothing: Nothing = { '@typed/Nothing': true }
Applies the function contained in a Maybe
to the value contained in a
second Maybe
.
See the code
export const ap: MaybeAp = curry2(__ap)
function __ap<A, B>(fn: Maybe<(value: A) => B>, maybe: Maybe<A>): Maybe<B> {
return chain(f => map(f, maybe), fn)
}
export interface MaybeAp {
<A, B>(fn: Maybe<(value: A) => B>, value: Maybe<A>): Maybe<B>
<A, B>(fn: Maybe<(value: A) => B>): (value: Maybe<A>) => Maybe<B>
}
Maps a Maybe
to another Maybe
.
See the code
export const chain: MaybeChain = curry2(__chain)
function __chain<A, B>(f: (value: A) => Maybe<B>, maybe: Maybe<A>): Maybe<B> {
return isNothing(maybe) ? maybe : f(fromJust(maybe))
}
export interface MaybeChain {
<A, B>(f: (value: A) => Maybe<B>, maybe: Maybe<A>): Maybe<B>
<A, B>(f: (value: A) => Maybe<B>): (maybe: Maybe<A>) => Maybe<B>
}
Applies a function with the values contained in 2 Maybes
if both are
Just
s. If either Maybe
s are Nothing
then Nothing
is returned.
See the code
export const combine: Combine = curry3(__combine)
export type Combine = {
<A, B, C>(f: (valueA: A, valueB: B) => C, maybeA: Maybe<A>, maybeB: Maybe<B>): Maybe<C>
<A, B, C>(f: (valueA: A, valueB: B) => C, maybeA: Maybe<A>): (maybeB: Maybe<B>) => Maybe<C>
<A, B, C>(f: (valueA: A, valueB: B) => C): {
(maybeA: Maybe<A>, maybeB: Maybe<B>): Maybe<C>
(maybeA: Maybe<A>): (maybeB: Maybe<B>) => Maybe<C>
}
}
function __combine<A, B, C>(
f: (valueA: A, valueB: B) => C,
maybeA: Maybe<A>,
maybeB: Maybe<B>
): Maybe<C> {
return combineArray(f, [maybeA, maybeB])
}
Applies a function with all of the values contained in an array of Maybe
s.
If any of the Maybe
s are Nothing
s then Nothing
is returned.
See the code
export const combineArray = curry2(__combineArray) as CombineArray
function __combineArray<R>(
f: (...values: Array<any>) => R,
maybes: ReadonlyArray<Maybe<any>>
): Maybe<R> {
const containsNothing = maybes.some(isNothing)
return containsNothing
? Nothing
: Just.of<R>(f(...(maybes as ReadonlyArray<Just<any>>).map(fromJust)))
}
export type CombineArray = {
<A, B, C>(f: (valueA: A, valueB: B) => C, maybes: [Maybe<A>, Maybe<B>]): Maybe<C>
<A, B, C, D>(
f: (valueA: A, valueB: B, valueC: C) => D,
maybes: [Maybe<A>, Maybe<B>, Maybe<C>]
): Maybe<D>
<A, B, C, D, E>(
f: (valueA: A, valueB: B, valueC: C, valueD: D) => E,
maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>]
): Maybe<E>
<A, B, C, D, E, F>(
f: (valueA: A, valueB: B, valueC: C, valueD: D, valueE: E) => F,
maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>, Maybe<E>]
): Maybe<F>
<A, B, C, D, E, F, G>(
f: (valueA: A, valueB: B, valueC: C, valueD: D, valueE: E, valueF: F) => G,
maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>, Maybe<E>, Maybe<F>]
): Maybe<G>
<A, B, C>(f: (valueA: A, valueB: B) => C): (maybes: [Maybe<A>, Maybe<B>]) => Maybe<C>
<A, B, C, D>(f: (valueA: A, valueB: B, valueC: C) => D): (
maybes: [Maybe<A>, Maybe<B>, Maybe<C>]
) => Maybe<D>
<A, B, C, D, E>(f: (valueA: A, valueB: B, valueC: C, valueD: D) => E): (
maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>]
) => Maybe<E>
<A, B, C, D, E, F>(f: (valueA: A, valueB: B, valueC: C, valueD: D, valueE: E) => F): (
maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>, Maybe<E>]
) => Maybe<F>
<A, B, C, D, E, F, G>(
f: (valueA: A, valueB: B, valueC: C, valueD: D, valueE: E, valueF: F) => G
): (maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>, Maybe<E>, Maybe<F>]) => Maybe<G>
(f: ArrayConstructor): {
<A, B>(maybes: [Maybe<A>, Maybe<B>]): Maybe<[A, B]>
<A, B, C>(maybes: [Maybe<A>, Maybe<B>, Maybe<C>]): Maybe<[A, B, C]>
<A, B, C, D>(maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>]): Maybe<[A, B, C, D]>
<A, B, C, D, E>(maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>, Maybe<E>]): Maybe<
[A, B, C, D, E]
>
<A, B, C, D, E, F>(maybes: [Maybe<A>, Maybe<B>, Maybe<C>, Maybe<D>, Maybe<E>, Maybe<F>]): Maybe<
[A, B, C, D, E, F]
>
}
<R>(f: (...values: Array<any>) => R, maybes: ReadonlyArray<Maybe<any>>): Maybe<R>
<R>(f: (...values: Array<any>) => R): (maybes: ReadonlyArray<Maybe<any>>) => Maybe<R>
}
Extract the value contained in a Just
See an example
import { fromJust, Just } from '@typed/maybe'
const value = fromJust(Just.of(1))
console.log(value) // logs '1'
See the code
export function fromJust<A>(just: Just<A>): A {
return just['@typed/Just']
}
Given a default value and a Maybe returns the default value if the Maybe is a Nothing or the value contained in a Just.
See the code
export const fromMaybe: FromMaybe = curry2(__fromMaybe)
function __fromMaybe<A>(defaultValue: A, maybe: Maybe<A>): A {
return isJust(maybe) ? fromJust(maybe) : defaultValue
}
export interface FromMaybe {
<A>(defaultValue: A, maybe: Maybe<A>): A
<A>(defaultValue: A): (maybe: Maybe<A>) => A
}
Given a Maybe<A> it returns true if the Maybe<A> is Just<A> or false if it is a Nothing.
See an example
import { isJust, Nothing, Maybe } from '@typed/maybe'
console.log(isJust(Nothing)) // logs false
console.log(isJust(Maybe.of(1))) // logs true
See the code
export function isJust<A>(maybe: Maybe<A>): maybe is Just<A> {
return maybe.hasOwnProperty('@typed/Just')
}
Given a Maybe<A> it returns false if the Maybe<A> is Just<A> or true if it is a Nothing.
See an example
import { isNothing, Maybe, Nothing } from '@typed/maybe'
console.log(isNothing(Nothing)) // logs true
console.log(isNothing(Maybe.of(1))) // logs false
See the code
export function isNothing<A>(maybe: Maybe<A>): maybe is Nothing {
return (maybe as Nothing)['@typed/Nothing'] === true
}
Applies a function to the value possibly contained in a Maybe
. If the
maybe is a Nothing
just the Nothing
is returned.
See the code
export const map: MaybeMap = curry2(__map)
function __map<A, B>(f: (value: A) => B, maybe: Maybe<A>): Maybe<B> {
return chain(a => Maybe.of(f(a)), maybe)
}
export interface MaybeMap {
<A, B>(f: (value: A) => B, maybe: Maybe<A>): Maybe<B>
<A, B>(f: (value: A) => B): (maybe: Maybe<A>) => Maybe<B>
}