Skip to content

Commit

Permalink
feat: readied applicable, array, renamed reducible
Browse files Browse the repository at this point in the history
  • Loading branch information
baetheus committed Oct 5, 2023
1 parent 0014f2f commit d424e8c
Show file tree
Hide file tree
Showing 48 changed files with 592 additions and 209 deletions.
Binary file added .fslckout
Binary file not shown.
85 changes: 82 additions & 3 deletions applicable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,86 @@ export function getApplicableCombinable<U extends Kind>(
) => Combinable<$<U, [A, B, C], [D], [E]>> {
return <A, B = never, C = never, D = unknown, E = unknown>(
{ combine }: Combinable<A>,
): Combinable<$<U, [A, B, C], [D], [E]>> => ({
combine: (second) => (first) => apply(first)(map(combine)(second)),
});
): Combinable<$<U, [A, B, C], [D], [E]>> => {
const _map = map(combine);
return {
combine: (second) => (first) => apply(first)(_map(second)),
};
};
}

/**
* Compose two Applicables into a new apply function.
*
* @since 2.0.0
*/
export function apply<U extends Kind, V extends Kind>(
U: Applicable<U>,
V: Applicable<V>,
): <
A,
B = never,
C = never,
D = unknown,
E = unknown,
J = never,
K = never,
L = unknown,
M = unknown,
>(
uva: $<U, [$<V, [A, B, C], [D], [E]>, J, K], [L], [M]>,
) => <I>(
uvfai: $<U, [$<V, [(a: A) => I, B, C], [D], [E]>, J, K], [L], [M]>,
) => $<U, [$<V, [I, B, C], [D], [E]>, J, K], [L], [M]> {
return <
A,
B = never,
C = never,
D = unknown,
E = unknown,
J = never,
K = never,
L = unknown,
M = unknown,
>(uva: $<U, [$<V, [A, B, C], [D], [E]>, J, K], [L], [M]>) =>
<I>(
uvfai: $<U, [$<V, [(a: A) => I, B, C], [D], [E]>, J, K], [L], [M]>,
): $<U, [$<V, [I, B, C], [D], [E]>, J, K], [L], [M]> => {
return U.apply(uva)(
U.map(
(vfai: $<V, [(a: A) => I, B, C], [D], [E]>) =>
(va: $<V, [A, B, C], [D], [E]>) => V.apply(va)(vfai),
)(uvfai),
);
};
}

/**
* @since 2.0.0
*/
export function applyFirst<U extends Kind>(
U: Applicable<U>,
): <I, B = never, C = never, D = unknown, E = unknown>(
second: $<U, [I, B, C], [D], [E]>,
) => <A>(first: $<U, [A, B, C], [D], [E]>) => $<U, [A, B, C], [D], [E]> {
return <I, B = never, C = never, D = unknown, E = unknown>(
second: $<U, [I, B, C], [D], [E]>,
) =>
<A>(first: $<U, [A, B, C], [D], [E]>): $<U, [A, B, C], [D], [E]> =>
U.apply(second)(U.map((a: A) => (_: I) => a)(first));
}

/**
* @since 2.0.0
*/
export function applySecond<U extends Kind>(
U: Applicable<U>,
): <I, B = never, C = never, D = unknown, E = unknown>(
second: $<U, [I, B, C], [D], [E]>,
) => <A>(first: $<U, [A, B, C], [D], [E]>) => $<U, [I, B, C], [D], [E]> {
return <I, B = never, C = never, D = unknown, E = unknown>(
second: $<U, [I, B, C], [D], [E]>,
) =>
<A>(first: $<U, [A, B, C], [D], [E]>): $<U, [I, B, C], [D], [E]> =>
U.apply(second)(U.map(() => (i: I) => i)(first));
}
45 changes: 34 additions & 11 deletions array.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import type { $, AnySub, Intersect, Kind, Out } from "./kind.ts";
import type { Applicable } from "./applicable.ts";
import type { Combinable } from "./combinable.ts";
import type { Comparable } from "./comparable.ts";
import type { Either } from "./either.ts";
import type { Filterable } from "./filterable.ts";
Expand All @@ -17,22 +18,21 @@ import type { Initializable } from "./initializable.ts";
import type { Mappable } from "./mappable.ts";
import type { Option } from "./option.ts";
import type { Pair } from "./pair.ts";
import type { Reducible } from "./reducible.ts";
import type { Foldable } from "./foldable.ts";
import type { Showable } from "./showable.ts";
import type { Sortable } from "./sortable.ts";
import type { Traversable } from "./traversable.ts";
import type { Wrappable } from "./wrappable.ts";

import { createBind, createTap } from "./flatmappable.ts";
import { createBindTo } from "./mappable.ts";
import { pair } from "./pair.ts";
import { isRight } from "./either.ts";
import { fromCompare } from "./comparable.ts";
import { fromSort, sign } from "./sortable.ts";
import { isSome, none, some } from "./option.ts";
import { identity, pipe } from "./fn.ts";

const NameReadonlyArray = "ReadonlyArray";
type NameReadonlyArray = typeof NameReadonlyArray;

/**
* This type can be used as a placeholder for an array of any type.
*
Expand Down Expand Up @@ -71,7 +71,6 @@ export type AnyNonEmptyArray = NonEmptyArray<any>;
* @since 2.0.0
*/
export interface KindArray extends Kind {
readonly name: NameReadonlyArray;
readonly kind: ReadonlyArray<Out<this, 0>>;
}

Expand Down Expand Up @@ -412,7 +411,7 @@ export function map<A, I>(
*
* const result = pipe(
* A.range(5, 1),
* A.reduce((sum, value, index) => sum + value + index, 0),
* A.fold((sum, value, index) => sum + value + index, 0),
* );
* // 0 + 0 + 0 = 0
* // 0 + 1 + 1 = 2
Expand All @@ -424,7 +423,7 @@ export function map<A, I>(
*
* @since 2.0.0
*/
export function reduce<A, O>(
export function fold<A, O>(
foao: (o: O, a: A, i: number) => O,
o: O,
): (ua: ReadonlyArray<A>) => O {
Expand Down Expand Up @@ -803,7 +802,7 @@ export function traverse<V extends Kind>(
favi: (a: A, i: number) => $<V, [I, J, K], [L], [M]>,
): (ua: ReadonlyArray<A>) => $<V, [ReadonlyArray<I>, J, K], [L], [M]> => {
const pusher = (is: I[]) => (i: I) => [...is, i];
return reduce(
return fold(
(vis, a: A, index) =>
pipe(
vis,
Expand Down Expand Up @@ -1129,7 +1128,7 @@ export function deleteAt(index: number) {
* sort(ordNumber)([3, 1, 2])
* // [1, 2, 3]
*
* @category combinators
* @since 2.0.0
*/
export function sort<B>(
O: Sortable<B>,
Expand Down Expand Up @@ -1283,6 +1282,15 @@ export function zip<A extends ReadonlyArray<AnyArray>>(
}
}

/**
* @since 2.0.0
*/
export function getCombinableArray<A>(): Combinable<ReadonlyArray<A>> {
return {
combine,
};
}

/**
* Given an instance Comparable<A> create a Comparable<ReadonlyArray<A>>.
*
Expand Down Expand Up @@ -1434,18 +1442,33 @@ export const MappableArray: Mappable<KindArray> = { map };
/**
* @since 2.0.0
*/
export const ReducibleArray: Reducible<KindArray> = { reduce };
export const FoldableArray: Foldable<KindArray> = { fold };

/**
* @since 2.0.0
*/
export const TraversableArray: Traversable<KindArray> = {
map,
reduce,
fold,
traverse,
};

/**
* @since 2.0.0
*/
export const WrappableArray: Wrappable<KindArray> = { wrap };

/**
* @since 2.0.0
*/
export const tap = createTap(FlatmappableArray);

/**
* @since 2.0.0
*/
export const bind = createBind(FlatmappableArray);

/**
* @since 2.0.0
*/
export const bindTo = createBindTo(MappableArray);
94 changes: 94 additions & 0 deletions async.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,55 @@
/**
* This file contains the Async algebraic data type. Async is a lazy,
* asynchronous adt that is useful for encapsulating anything from file reads
* and network requests to timers and loops.
*
* @module Async
* @since 2.0.0
*/

import type { Kind, Out } from "./kind.ts";
import type { Applicable } from "./applicable.ts";
import type { Combinable } from "./combinable.ts";
import type { Initializable } from "./initializable.ts";
import type { Flatmappable } from "./flatmappable.ts";
import type { Mappable } from "./mappable.ts";
import type { Sync } from "./sync.ts";
import type { Wrappable } from "./wrappable.ts";

import { createBindTo } from "./mappable.ts";
import { createBind, createTap } from "./flatmappable.ts";
import { resolve, wait } from "./promise.ts";
import { handleThrow } from "./fn.ts";

/**
* @since 2.0.0
*/
export type Async<A> = Sync<Promise<A>>;

/**
* @since 2.0.0
*/
export interface KindAsync extends Kind {
readonly kind: Async<Out<this, 0>>;
}

/**
* @since 2.0.0
*/
export function delay(ms: number): <A>(ma: Async<A>) => Async<A> {
return (ta) => () => wait(ms).then(ta);
}

/**
* @since 2.0.0
*/
export function fromSync<A>(fa: Sync<A>): Async<A> {
return () => resolve(fa());
}

/**
* @since 2.0.0
*/
export function tryCatch<AS extends unknown[], A>(
fasr: (...as: AS) => A | PromiseLike<A>,
onThrow: (e: unknown, as: AS) => A,
Expand All @@ -36,41 +64,107 @@ export function tryCatch<AS extends unknown[], A>(
};
}

/**
* @since 2.0.0
*/
export function wrap<A>(a: A): Async<A> {
return () => resolve(a);
}

/**
* @since 2.0.0
*/
export function map<A, I>(fai: (a: A) => I): (ta: Async<A>) => Async<I> {
return (ta) => () => ta().then(fai);
}

/**
* @since 2.0.0
*/
export function apply<A>(
ua: Async<A>,
): <I>(ufai: Async<(a: A) => I>) => Async<I> {
return (ufai) => () => Promise.all([ufai(), ua()]).then(([fai, a]) => fai(a));
}

/**
* @since 2.0.0
*/
export function applySequential<A>(
ua: Async<A>,
): <I>(ufai: Async<(a: A) => I>) => Async<I> {
return (ufai) => async () => (await ufai())(await ua());
}

/**
* @since 2.0.0
*/
export function flatmap<A, I>(
fati: (a: A) => Async<I>,
): (ta: Async<A>) => Async<I> {
return (ta) => () => ta().then((a) => fati(a)());
}

/**
* @since 2.0.0
*/
export function getCombinableAsync<A>(
{ combine }: Combinable<A>,
): Combinable<Async<A>> {
return {
combine: (second) => (first) => async () =>
combine(await second())(await first()),
};
}

/**
* @since 2.0.0
*/
export function getInitializableAsync<A>(
I: Initializable<A>,
): Initializable<Async<A>> {
return {
init: () => async () => await I.init(),
...getCombinableAsync(I),
};
}

/**
* @since 2.0.0
*/
export const WrappableAsync: Wrappable<KindAsync> = { wrap };

/**
* @since 2.0.0
*/
export const ApplicableAsync: Applicable<KindAsync> = { apply, map, wrap };

/**
* @since 2.0.0
*/
export const MappableAsync: Mappable<KindAsync> = { map };

/**
* @since 2.0.0
*/
export const FlatmappableAsync: Flatmappable<KindAsync> = {
apply,
flatmap,
map,
wrap,
};

/**
* @since 2.0.0
*/
export const tap = createTap(FlatmappableAsync);

/**
* @since 2.0.0
*/
export const bind = createBind(FlatmappableAsync);

/**
* @since 2.0.0
*/
export const bindTo = createBindTo(MappableAsync);
Loading

0 comments on commit d424e8c

Please sign in to comment.