From 023b512bd0b3d5a91bbe85b262e8762e5ce3ac21 Mon Sep 17 00:00:00 2001 From: Giulio Canti Date: Wed, 29 Nov 2023 09:56:35 +0100 Subject: [PATCH] List: merge NonEmpty APIs into base ones (#1716) --- .changeset/popular-cows-pretend.md | 5 ++ docs/modules/Chunk.ts.md | 4 +- docs/modules/List.ts.md | 84 +++++++++++----------- dtslint/List.ts | 107 ++++++++++++++++++++--------- src/Chunk.ts | 4 +- src/List.ts | 79 ++++++++++----------- test/List.test.ts | 8 --- 7 files changed, 162 insertions(+), 129 deletions(-) create mode 100644 .changeset/popular-cows-pretend.md diff --git a/.changeset/popular-cows-pretend.md b/.changeset/popular-cows-pretend.md new file mode 100644 index 0000000000..58c58747ad --- /dev/null +++ b/.changeset/popular-cows-pretend.md @@ -0,0 +1,5 @@ +--- +"effect": minor +--- + +List: merge NonEmpty APIs into base ones diff --git a/docs/modules/Chunk.ts.md b/docs/modules/Chunk.ts.md index 636ddb2d3f..70f3f7c2af 100644 --- a/docs/modules/Chunk.ts.md +++ b/docs/modules/Chunk.ts.md @@ -193,7 +193,7 @@ Added in v2.0.0 ## prependAll -Concatenates two chunks, combining their elements. +Prepends the specified prefix chunk to the beginning of the specified chunk. If either chunk is non-empty, the result is also a non-empty chunk. **Signature** @@ -1024,7 +1024,7 @@ Added in v2.0.0 ## flatMap -Returns a chunk with the elements mapped by the specified function. +Applies a function to each element in a chunk and returns a new chunk containing the concatenated mapped elements. **Signature** diff --git a/docs/modules/List.ts.md b/docs/modules/List.ts.md index ac5ff0464e..1c608958e2 100644 --- a/docs/modules/List.ts.md +++ b/docs/modules/List.ts.md @@ -34,10 +34,8 @@ Added in v2.0.0 - [concatenating](#concatenating) - [append](#append) - [appendAll](#appendall) - - [appendAllNonEmpty](#appendallnonempty) - [prepend](#prepend) - [prependAll](#prependall) - - [prependAllNonEmpty](#prependallnonempty) - [prependAllReversed](#prependallreversed) - [constructors](#constructors) - [cons](#cons) @@ -76,7 +74,6 @@ Added in v2.0.0 - [isNil](#isnil) - [sequencing](#sequencing) - [flatMap](#flatmap) - - [flatMapNonEmpty](#flatmapnonempty) - [symbol](#symbol) - [TypeId](#typeid) - [TypeId (type alias)](#typeid-type-alias) @@ -88,6 +85,7 @@ Added in v2.0.0 - [List (namespace)](#list-namespace) - [Infer (type alias)](#infer-type-alias) - [With (type alias)](#with-type-alias) + - [With2 (type alias)](#with2-type-alias) --- @@ -251,30 +249,26 @@ Added in v2.0.0 ## appendAll -Concatentates the specified lists together. +Concatenates two lists, combining their elements. +If either list is non-empty, the result is also a non-empty list. **Signature** ```ts export declare const appendAll: { - (that: List): (self: List) => List + , T extends List>(that: T): (self: S) => List.With2 | List.Infer> + (self: List, that: Cons): Cons + (self: Cons, that: List): Cons (self: List, that: List): List } ``` -Added in v2.0.0 - -## appendAllNonEmpty - -**Signature** +**Example** ```ts -export declare const appendAllNonEmpty: { - (that: Cons): (self: List) => Cons - (that: List): (self: Cons) => Cons - (self: List, that: Cons): Cons - (self: Cons, that: List): Cons -} +import * as List from "effect/List" + +assert.deepStrictEqual(List.make(1, 2).pipe(List.appendAll(List.make("a", "b")), List.toArray), [1, 2, "a", "b"]) ``` Added in v2.0.0 @@ -297,29 +291,25 @@ Added in v2.0.0 ## prependAll Prepends the specified prefix list to the beginning of the specified list. +If either list is non-empty, the result is also a non-empty list. **Signature** ```ts export declare const prependAll: { - (prefix: List): (self: List) => List - (self: List, prefix: List): List + , T extends List>(that: T): (self: S) => List.With2 | List.Infer> + (self: List, that: Cons): Cons + (self: Cons, that: List): Cons + (self: List, that: List): List } ``` -Added in v2.0.0 - -## prependAllNonEmpty - -**Signature** +**Example** ```ts -export declare const prependAllNonEmpty: { - (that: Cons): (self: List) => Cons - (that: List): (self: Cons) => Cons - (self: List, that: Cons): Cons - (self: Cons, that: List): Cons -} +import * as List from "effect/List" + +assert.deepStrictEqual(List.make(1, 2).pipe(List.prependAll(List.make("a", "b")), List.toArray), ["a", "b", 1, 2]) ``` Added in v2.0.0 @@ -709,27 +699,17 @@ Added in v2.0.0 ## flatMap -Flat maps a list using the specified function. +Applies a function to each element in a list and returns a new list containing the concatenated mapped elements. **Signature** ```ts export declare const flatMap: { - (f: (a: A) => List): (self: List) => List - (self: List, f: (a: A) => List): List -} -``` - -Added in v2.0.0 - -## flatMapNonEmpty - -**Signature** - -```ts -export declare const flatMapNonEmpty: { - (f: (a: A) => Cons): (self: Cons) => Cons - (self: Cons, f: (a: A) => Cons): Cons + , T extends List>( + f: (a: List.Infer, i: number) => T + ): (self: S) => List.With2> + (self: Cons, f: (a: A, i: number) => Cons): Cons + (self: List, f: (a: A, i: number) => List): List } ``` @@ -820,3 +800,17 @@ export type With, A> = T extends Cons ? Cons : List< ``` Added in v2.0.0 + +### With2 (type alias) + +**Signature** + +```ts +export type With2, T extends List, A> = S extends Cons + ? Cons + : T extends Cons + ? Cons + : List +``` + +Added in v2.0.0 diff --git a/dtslint/List.ts b/dtslint/List.ts index a574e3670b..0e8ffad011 100644 --- a/dtslint/List.ts +++ b/dtslint/List.ts @@ -3,9 +3,10 @@ import * as List from "effect/List" import * as Predicate from "effect/Predicate" declare const numbers: List.List +declare const strings: List.List declare const nonEmptyNumbers: List.Cons +declare const nonEmptyStrings: List.Cons declare const numbersOrStrings: List.List -declare const nonEmptyNumbersOrStrings: List.Cons declare const predicateNumbersOrStrings: Predicate.Predicate @@ -84,22 +85,6 @@ List.append(numbersOrStrings, true) // $ExpectType Cons List.append(true)(numbersOrStrings) -// ------------------------------------------------------------------------------------- -// appendAllNonEmpty -// ------------------------------------------------------------------------------------- - -// $ExpectType Cons -List.appendAllNonEmpty(numbersOrStrings, nonEmptyNumbersOrStrings) - -// $ExpectType Cons -List.appendAllNonEmpty(numbersOrStrings)(nonEmptyNumbersOrStrings) - -// $ExpectType Cons -List.appendAllNonEmpty(nonEmptyNumbersOrStrings, numbersOrStrings) - -// $ExpectType Cons -List.appendAllNonEmpty(nonEmptyNumbersOrStrings)(numbersOrStrings) - // ------------------------------------------------------------------------------------- // prepend // ------------------------------------------------------------------------------------- @@ -110,22 +95,6 @@ List.prepend(numbersOrStrings, true) // $ExpectType Cons List.prepend(true)(numbersOrStrings) -// ------------------------------------------------------------------------------------- -// prependAllNonEmpty -// ------------------------------------------------------------------------------------- - -// $ExpectType Cons -List.prependAllNonEmpty(numbersOrStrings, nonEmptyNumbersOrStrings) - -// $ExpectType Cons -List.prependAllNonEmpty(numbersOrStrings)(nonEmptyNumbersOrStrings) - -// $ExpectType Cons -List.prependAllNonEmpty(nonEmptyNumbersOrStrings, numbersOrStrings) - -// $ExpectType Cons -List.prependAllNonEmpty(nonEmptyNumbersOrStrings)(numbersOrStrings) - // ------------------------------------------------------------------------------------- // map // ------------------------------------------------------------------------------------- @@ -201,3 +170,75 @@ List.findFirst(numbersOrStrings, Predicate.isNumber) // $ExpectType Option pipe(numbersOrStrings, List.findFirst(Predicate.isNumber)) + +// ------------------------------------------------------------------------------------- +// appendAll +// ------------------------------------------------------------------------------------- + +// $ExpectType List +List.appendAll(strings, numbers) + +// $ExpectType List +pipe(strings, List.appendAll(numbers)) + +// $ExpectType Cons +List.appendAll(nonEmptyStrings, numbers) + +// $ExpectType Cons +pipe(nonEmptyStrings, List.appendAll(numbers)) + +// $ExpectType Cons +List.appendAll(strings, nonEmptyNumbers) + +// $ExpectType Cons +pipe(strings, List.appendAll(nonEmptyNumbers)) + +// $ExpectType Cons +List.appendAll(nonEmptyStrings, nonEmptyNumbers) + +// $ExpectType Cons +pipe(nonEmptyStrings, List.appendAll(nonEmptyNumbers)) + +// ------------------------------------------------------------------------------------- +// prependAll +// ------------------------------------------------------------------------------------- + +// $ExpectType List +List.prependAll(strings, numbers) + +// $ExpectType List +pipe(strings, List.prependAll(numbers)) + +// $ExpectType Cons +List.prependAll(nonEmptyStrings, numbers) + +// $ExpectType Cons +pipe(nonEmptyStrings, List.prependAll(numbers)) + +// $ExpectType Cons +List.prependAll(strings, nonEmptyNumbers) + +// $ExpectType Cons +pipe(strings, List.prependAll(nonEmptyNumbers)) + +// $ExpectType Cons +List.prependAll(nonEmptyStrings, nonEmptyNumbers) + +// $ExpectType Cons +pipe(nonEmptyStrings, List.prependAll(nonEmptyNumbers)) + +// ------------------------------------------------------------------------------------- +// flatMap +// ------------------------------------------------------------------------------------- + +// $ExpectType List +List.flatMap(strings, (_) => List.empty()) + +// $ExpectType List +List.flatMap(strings, (s) => List.of(s.length)) + +// $ExpectType List +List.flatMap(nonEmptyStrings, (_s) => List.empty()) + +// $ExpectType Cons +List.flatMap(nonEmptyStrings, (s) => List.of(s.length)) diff --git a/src/Chunk.ts b/src/Chunk.ts index b12cad6402..2f7a81eca7 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -547,7 +547,7 @@ export const dropWhile: { }) /** - * Concatenates two chunks, combining their elements. + * Prepends the specified prefix chunk to the beginning of the specified chunk. * If either chunk is non-empty, the result is also a non-empty chunk. * * @example @@ -680,7 +680,7 @@ export const filterMapWhile: { export const compact = (self: Chunk>): Chunk => filterMap(self, identity) /** - * Returns a chunk with the elements mapped by the specified function. + * Applies a function to each element in a chunk and returns a new chunk containing the concatenated mapped elements. * * @since 2.0.0 * @category sequencing diff --git a/src/List.ts b/src/List.ts index 3e7cb2bf00..499fe66493 100644 --- a/src/List.ts +++ b/src/List.ts @@ -315,29 +315,29 @@ export const make = ]>( export const append: { (element: B): (self: List) => Cons (self: List, element: B): Cons -} = dual(2, (self: List, element: B): Cons => appendAllNonEmpty(self, of(element))) +} = dual(2, (self: List, element: B): Cons => appendAll(self, of(element))) /** - * Concatentates the specified lists together. + * Concatenates two lists, combining their elements. + * If either list is non-empty, the result is also a non-empty list. + * + * @example + * import * as List from "effect/List" + * + * assert.deepStrictEqual( + * List.make(1, 2).pipe(List.appendAll(List.make("a", "b")), List.toArray), + * [1, 2, "a", "b"] + * ) * * @category concatenating * @since 2.0.0 */ export const appendAll: { - (that: List): (self: List) => List - (self: List, that: List): List -} = dual(2, (self: List, that: List): List => prependAll(that, self)) - -/** - * @category concatenating - * @since 2.0.0 - */ -export const appendAllNonEmpty: { - (that: Cons): (self: List) => Cons - (that: List): (self: Cons) => Cons + , T extends List>(that: T): (self: S) => List.With2 | List.Infer> (self: List, that: Cons): Cons (self: Cons, that: List): Cons -} = dual(2, (self: Cons, that: List): Cons => appendAll(self, that) as any) + (self: List, that: List): List +} = dual(2, (self: List, that: List): List => prependAll(that, self)) /** * Prepends the specified element to the beginning of the list. @@ -352,13 +352,24 @@ export const prepend: { /** * Prepends the specified prefix list to the beginning of the specified list. + * If either list is non-empty, the result is also a non-empty list. + * + * @example + * import * as List from "effect/List" + * + * assert.deepStrictEqual( + * List.make(1, 2).pipe(List.prependAll(List.make("a", "b")), List.toArray), + * ["a", "b", 1, 2] + * ) * * @category concatenating * @since 2.0.0 */ export const prependAll: { - (prefix: List): (self: List) => List - (self: List, prefix: List): List + , T extends List>(that: T): (self: S) => List.With2 | List.Infer> + (self: List, that: Cons): Cons + (self: Cons, that: List): Cons + (self: List, that: List): List } = dual(2, (self: List, prefix: List): List => { if (isNil(self)) { return prefix @@ -378,17 +389,6 @@ export const prependAll: { } }) -/** - * @category concatenating - * @since 2.0.0 - */ -export const prependAllNonEmpty: { - (that: Cons): (self: List) => Cons - (that: List): (self: Cons) => Cons - (self: List, that: Cons): Cons - (self: Cons, that: List): Cons -} = dual(2, (self: Cons, that: List): Cons => prependAll(self, that) as any) - /** * Prepends the specified prefix list (in reverse order) to the beginning of the * specified list. @@ -633,14 +633,17 @@ export const findFirst: { }) /** - * Flat maps a list using the specified function. + * Applies a function to each element in a list and returns a new list containing the concatenated mapped elements. * * @since 2.0.0 * @category sequencing */ export const flatMap: { - (f: (a: A) => List): (self: List) => List - (self: List, f: (a: A) => List): List + , T extends List>( + f: (a: List.Infer, i: number) => T + ): (self: S) => List.With2> + (self: Cons, f: (a: A, i: number) => Cons): Cons + (self: List, f: (a: A, i: number) => List): List } = dual(2, (self: List, f: (a: A) => List): List => { let rest = self let head: MutableCons | undefined = undefined @@ -665,15 +668,6 @@ export const flatMap: { return head }) -/** - * @category sequencing - * @since 2.0.0 - */ -export const flatMapNonEmpty: { - (f: (a: A) => Cons): (self: Cons) => Cons - (self: Cons, f: (a: A) => Cons): Cons -} = flatMap as any - /** * Applies the specified function to each element of the `List`. * @@ -722,6 +716,13 @@ export declare namespace List { * @since 2.0.0 */ export type With, A> = T extends Cons ? Cons : List + + /** + * @since 2.0.0 + */ + export type With2, T extends List, A> = S extends Cons ? Cons + : T extends Cons ? Cons + : List } /** diff --git a/test/List.test.ts b/test/List.test.ts index d015ee791a..08c195949f 100644 --- a/test/List.test.ts +++ b/test/List.test.ts @@ -23,8 +23,6 @@ describe.concurrent("List", () => { expect(List.size).exist expect(List.filter).exist expect(List.filterMap).exist - expect(List.appendAllNonEmpty).exist - expect(List.prependAllNonEmpty).exist }) it("is an iterable", () => { @@ -79,12 +77,6 @@ describe.concurrent("List", () => { ) }) - it("flatMapNonEmpty", () => { - expect(List.flatMapNonEmpty(List.make(1, 2, 3, 4), (n) => List.make(n - 1, n + 1))).toEqual( - List.make(0, 2, 1, 3, 2, 4, 3, 5) - ) - }) - it("forEach", () => { const as: Array = [] List.forEach(List.make(1, 2, 3, 4), (n) => as.push(n))