From 3a64d691e40f677c9937faefd5b182bb50ab1828 Mon Sep 17 00:00:00 2001 From: gcanti Date: Mon, 28 Nov 2022 14:11:54 +0100 Subject: [PATCH 1/3] remove Compactable, Filterable, TraversableFilterable and /data folder also remove SemiCoproduct/coproductEither --- .changeset/swift-melons-reflect.md | 5 + dtslint/ts4.7/SemiProduct.ts | 2 +- src/data/Either.ts | 36 -- src/data/Option.ts | 35 -- src/index.ts | 37 +- src/internal/Either.ts | 41 -- src/internal/Option.ts | 24 -- src/typeclass/Compactable.ts | 46 -- src/typeclass/Filterable.ts | 89 ---- src/typeclass/SemiCoproduct.ts | 19 - src/typeclass/TraversableFilterable.ts | 107 ----- test/data/Either.ts | 64 +++ test/{test-data => data}/NonEmptyArray.ts | 0 .../NonEmptyReadonlyArray.ts | 0 test/{test-data => data}/Option.ts | 406 +----------------- test/{test-data => data}/Predicate.ts | 0 test/{test-data => data}/ReadonlyArray.ts | 54 +-- test/{test-data => data}/boolean.ts | 0 test/{test-data => data}/number.ts | 0 test/{test-data => data}/string.ts | 0 test/internal/Either.ts | 14 - test/limbo/FilterableWithIndex.ts | 104 ----- test/test-data/Either.ts | 39 -- test/typeclass/Applicative.ts | 4 +- test/typeclass/Bicovariant.ts | 6 +- test/typeclass/Bounded.ts | 2 +- test/typeclass/Chainable.ts | 2 +- test/typeclass/Compactable.ts | 25 -- test/typeclass/Contravariant.ts | 4 +- test/typeclass/Coproduct.ts | 2 +- test/typeclass/Covariant.ts | 4 +- test/typeclass/CovariantWithIndex.ts | 2 +- test/typeclass/Filterable.ts | 44 -- test/typeclass/FilterableWithIndex.ts | 55 --- test/typeclass/FlatMap.ts | 2 +- test/typeclass/Foldable.ts | 6 +- test/typeclass/FoldableWithIndex.ts | 6 +- test/typeclass/Invariant.ts | 6 +- test/typeclass/Monoid.ts | 4 +- test/typeclass/NonEmptyTraversable.ts | 4 +- test/typeclass/Of.ts | 4 +- test/typeclass/Order.ts | 8 +- test/typeclass/Product.ts | 8 +- test/typeclass/SemiApplicative.ts | 4 +- test/typeclass/SemiCoproduct.ts | 12 +- test/typeclass/SemiProduct.ts | 10 +- test/typeclass/Semigroup.ts | 4 +- test/typeclass/Traversable.ts | 4 +- test/typeclass/TraversableFilterable.ts | 36 -- test/typeclass/TraversableWithIndex.ts | 4 +- vitest.config.ts | 2 +- 51 files changed, 129 insertions(+), 1267 deletions(-) create mode 100644 .changeset/swift-melons-reflect.md delete mode 100644 src/data/Either.ts delete mode 100644 src/data/Option.ts delete mode 100644 src/internal/Either.ts delete mode 100644 src/internal/Option.ts delete mode 100644 src/typeclass/Compactable.ts delete mode 100644 src/typeclass/Filterable.ts delete mode 100644 src/typeclass/TraversableFilterable.ts create mode 100644 test/data/Either.ts rename test/{test-data => data}/NonEmptyArray.ts (100%) rename test/{test-data => data}/NonEmptyReadonlyArray.ts (100%) rename test/{test-data => data}/Option.ts (64%) rename test/{test-data => data}/Predicate.ts (100%) rename test/{test-data => data}/ReadonlyArray.ts (78%) rename test/{test-data => data}/boolean.ts (100%) rename test/{test-data => data}/number.ts (100%) rename test/{test-data => data}/string.ts (100%) delete mode 100644 test/internal/Either.ts delete mode 100644 test/limbo/FilterableWithIndex.ts delete mode 100644 test/test-data/Either.ts delete mode 100644 test/typeclass/Compactable.ts delete mode 100644 test/typeclass/Filterable.ts delete mode 100644 test/typeclass/FilterableWithIndex.ts delete mode 100644 test/typeclass/TraversableFilterable.ts diff --git a/.changeset/swift-melons-reflect.md b/.changeset/swift-melons-reflect.md new file mode 100644 index 000000000..6c5950291 --- /dev/null +++ b/.changeset/swift-melons-reflect.md @@ -0,0 +1,5 @@ +--- +"@fp-ts/core": patch +--- + +remove Compactable, Filterable, TraversableFilterable and /data folder diff --git a/dtslint/ts4.7/SemiProduct.ts b/dtslint/ts4.7/SemiProduct.ts index 8999c2545..e4024d816 100644 --- a/dtslint/ts4.7/SemiProduct.ts +++ b/dtslint/ts4.7/SemiProduct.ts @@ -1,4 +1,4 @@ -import { OptionTypeLambda } from "@fp-ts/core/data/Option" +import { OptionTypeLambda } from "@fp-ts/core/test/data/Option" import * as _ from "@fp-ts/core/typeclass/SemiProduct" export declare const SemiProduct: _.SemiProduct diff --git a/src/data/Either.ts b/src/data/Either.ts deleted file mode 100644 index 9fdd1920b..000000000 --- a/src/data/Either.ts +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @since 1.0.0 - */ -import type { TypeLambda } from "@fp-ts/core/HKT" - -/** - * @category models - * @since 1.0.0 - */ -export interface Left { - readonly _tag: "Left" - readonly left: E -} - -/** - * @category models - * @since 1.0.0 - */ -export interface Right { - readonly _tag: "Right" - readonly right: A -} - -/** - * @category models - * @since 1.0.0 - */ -export type Either = Left | Right - -/** - * @category type lambdas - * @since 1.0.0 - */ -export interface EitherTypeLambda extends TypeLambda { - readonly type: Either -} diff --git a/src/data/Option.ts b/src/data/Option.ts deleted file mode 100644 index 7fb5f2b6c..000000000 --- a/src/data/Option.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @since 1.0.0 - */ -import type { TypeLambda } from "@fp-ts/core/HKT" - -/** - * @category models - * @since 1.0.0 - */ -export interface None { - readonly _tag: "None" -} - -/** - * @category models - * @since 1.0.0 - */ -export interface Some { - readonly _tag: "Some" - readonly value: A -} - -/** - * @category models - * @since 1.0.0 - */ -export type Option = None | Some - -/** - * @category type lambdas - * @since 1.0.0 - */ -export interface OptionTypeLambda extends TypeLambda { - readonly type: Option -} diff --git a/src/index.ts b/src/index.ts index ebfee7123..cd437d1bb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,11 +17,9 @@ import * as applicative from "@fp-ts/core/typeclass/Applicative" import * as bicovariant from "@fp-ts/core/typeclass/Bicovariant" import * as bounded from "@fp-ts/core/typeclass/Bounded" import * as chainable from "@fp-ts/core/typeclass/Chainable" -import * as compactable from "@fp-ts/core/typeclass/Compactable" import * as contravariant from "@fp-ts/core/typeclass/Contravariant" import * as coproduct from "@fp-ts/core/typeclass/Coproduct" import * as covariant from "@fp-ts/core/typeclass/Covariant" -import * as filterable from "@fp-ts/core/typeclass/Filterable" import * as flatMap from "@fp-ts/core/typeclass/FlatMap" import * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" @@ -38,14 +36,6 @@ import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import * as traversable from "@fp-ts/core/typeclass/Traversable" -import * as traversableFilterable from "@fp-ts/core/typeclass/TraversableFilterable" - -// ------------------------------------------------------------------------------------- -// data types -// ------------------------------------------------------------------------------------- - -import * as either from "@fp-ts/core/data/Either" -import * as option from "@fp-ts/core/data/Option" export { /** @@ -73,11 +63,6 @@ export { * @since 1.0.0 */ chainable, - /** - * @category typeclass - * @since 1.0.0 - */ - compactable, /** * @category typeclass * @since 1.0.0 @@ -93,16 +78,6 @@ export { * @since 1.0.0 */ covariant, - /** - * @category data types - * @since 1.0.0 - */ - either, - /** - * @category typeclass - * @since 1.0.0 - */ - filterable, /** * @category typeclass * @since 1.0.0 @@ -142,11 +117,6 @@ export { * @since 1.0.0 */ of, - /** - * @category data types - * @since 1.0.0 - */ - option, /** * @category typeclass * @since 1.0.0 @@ -191,10 +161,5 @@ export { * @category typeclass * @since 1.0.0 */ - traversable, - /** - * @category typeclass - * @since 1.0.0 - */ - traversableFilterable + traversable } diff --git a/src/internal/Either.ts b/src/internal/Either.ts deleted file mode 100644 index 752a98f44..000000000 --- a/src/internal/Either.ts +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @since 1.0.0 - */ - -import type { Either, Left, Right } from "@fp-ts/core/data/Either" -import type { Option } from "@fp-ts/core/data/Option" -import * as option from "@fp-ts/core/internal/Option" - -/** - * @since 1.0.0 - */ -export const left = (e: E): Either => ({ _tag: "Left", left: e }) - -/** - * @since 1.0.0 - */ -export const right = (a: A): Either => ({ _tag: "Right", right: a }) - -/** - * @since 1.0.0 - */ -export const isLeft = (self: Either): self is Left => self._tag === "Left" - -/** - * @since 1.0.0 - */ -export const isRight = (self: Either): self is Right => self._tag === "Right" - -/** - * @since 1.0.0 - */ -export const getLeft = ( - self: Either -): Option => (isRight(self) ? option.none : option.some(self.left)) - -/** - * @since 1.0.0 - */ -export const getRight = ( - self: Either -): Option => (isLeft(self) ? option.none : option.some(self.right)) diff --git a/src/internal/Option.ts b/src/internal/Option.ts deleted file mode 100644 index e6891324e..000000000 --- a/src/internal/Option.ts +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @since 1.0.0 - */ -import type { None, Option, Some } from "@fp-ts/core/data/Option" - -/** - * @since 1.0.0 - */ -export const none: Option = { _tag: "None" } - -/** - * @since 1.0.0 - */ -export const some = (a: A): Option => ({ _tag: "Some", value: a }) - -/** - * @since 1.0.0 - */ -export const isNone = (fa: Option): fa is None => fa._tag === "None" - -/** - * @since 1.0.0 - */ -export const isSome = (fa: Option): fa is Some => fa._tag === "Some" diff --git a/src/typeclass/Compactable.ts b/src/typeclass/Compactable.ts deleted file mode 100644 index bcd41ad18..000000000 --- a/src/typeclass/Compactable.ts +++ /dev/null @@ -1,46 +0,0 @@ -/** - * `Compactable` represents data structures which can be _compacted_/_separated_. - * - * @since 1.0.0 - */ -import type { Either } from "@fp-ts/core/data/Either" -import type { Option } from "@fp-ts/core/data/Option" -import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" -import type { Covariant } from "@fp-ts/core/typeclass/Covariant" - -/** - * @category models - * @since 1.0.0 - */ -export interface Compactable extends TypeClass { - readonly compact: (self: Kind>) => Kind -} - -/** - * Returns a default `compact` composition. - * - * @since 1.0.0 - */ -export const compactComposition = ( - F: Covariant, - G: Compactable -): (( - self: Kind>> -) => Kind>) => F.map(G.compact) - -/** - * @since 1.0.0 - */ -export const separate = ( - F: Covariant & Compactable -) => - ( - self: Kind> - ): readonly [Kind, Kind] => { - return [ - pipe(self, F.map(either.getLeft), F.compact), - pipe(self, F.map(either.getRight), F.compact) - ] - } diff --git a/src/typeclass/Filterable.ts b/src/typeclass/Filterable.ts deleted file mode 100644 index 2f8bc38fe..000000000 --- a/src/typeclass/Filterable.ts +++ /dev/null @@ -1,89 +0,0 @@ -/** - * `Filterable` represents data structures which can be _partitioned_/_filtered_. - * - * @since 1.0.0 - */ -import type { Either } from "@fp-ts/core/data/Either" -import type { Option } from "@fp-ts/core/data/Option" -import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" -import * as option from "@fp-ts/core/internal/Option" -import type { Covariant } from "@fp-ts/core/typeclass/Covariant" - -/** - * @category models - * @since 1.0.0 - */ -export interface Filterable extends TypeClass { - readonly filterMap: ( - f: (a: A) => Option - ) => (self: Kind) => Kind -} - -/** - * Returns a default `filterMap` composition. - * - * @since 1.0.0 - */ -export const filterMapComposition = ( - F: Covariant, - G: Filterable -) => - ( - f: (a: A) => Option - ): ( - self: Kind> - ) => Kind> => F.map(G.filterMap(f)) - -/** - * @since 1.0.0 - */ -export const filter: ( - F: Filterable -) => { - (refinement: (a: A) => a is B): ( - self: Kind - ) => Kind - ( - predicate: (a: A) => boolean - ): (self: Kind) => Kind -} = (Filterable: Filterable) => - ( - predicate: (a: A) => boolean - ): ((self: Kind) => Kind) => - Filterable.filterMap(b => (predicate(b) ? option.some(b) : option.none)) - -/** - * @since 1.0.0 - */ -export const partitionMap = (F: Filterable) => - (f: (a: A) => Either) => - ( - self: Kind - ): readonly [Kind, Kind] => { - return [ - pipe(self, F.filterMap(a => either.getLeft(f(a)))), - pipe(self, F.filterMap(a => either.getRight(f(a)))) - ] - } - -/** - * @since 1.0.0 - */ -export const partition: ( - F: Filterable -) => { - (refinement: (a: A) => a is B): ( - self: Kind - ) => readonly [Kind, Kind] - (predicate: (a: A) => boolean): ( - self: Kind - ) => readonly [Kind, Kind] -} = (Filterable: Filterable) => - ( - predicate: (a: A) => boolean - ): (( - self: Kind - ) => readonly [Kind, Kind]) => - partitionMap(Filterable)(b => (predicate(b) ? either.right(b) : either.left(b))) diff --git a/src/typeclass/SemiCoproduct.ts b/src/typeclass/SemiCoproduct.ts index c7527426f..d13d6e044 100644 --- a/src/typeclass/SemiCoproduct.ts +++ b/src/typeclass/SemiCoproduct.ts @@ -1,10 +1,7 @@ /** * @since 1.0.0 */ -import type { Either, Left, Right } from "@fp-ts/core/data/Either" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" import type { Invariant } from "@fp-ts/core/typeclass/Invariant" import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" @@ -34,19 +31,3 @@ export const getSemigroup = (F: SemiCoproduct) => combine: F.coproduct, combineMany: F.coproductMany }) - -/** - * @since 1.0.0 - */ -export const coproductEither = (F: SemiCoproduct) => - ( - that: Kind - ) => - ( - self: Kind - ): Kind> => - pipe( - self, - F.imap(a => either.left(a) as Left, e => e.left), - F.coproduct(pipe(that, F.imap(b => either.right(b) as Right, e => e.right))) - ) diff --git a/src/typeclass/TraversableFilterable.ts b/src/typeclass/TraversableFilterable.ts deleted file mode 100644 index a791ec9f4..000000000 --- a/src/typeclass/TraversableFilterable.ts +++ /dev/null @@ -1,107 +0,0 @@ -/** - * `TraversableFilterable` represents data structures which can be _partitioned_ with effects in some `Applicative` functor. - * - * @since 1.0.0 - */ -import type { Either } from "@fp-ts/core/data/Either" -import type { Option } from "@fp-ts/core/data/Option" -import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" -import * as option from "@fp-ts/core/internal/Option" -import type { Applicative } from "@fp-ts/core/typeclass/Applicative" -import * as compactable from "@fp-ts/core/typeclass/Compactable" -import type { Compactable } from "@fp-ts/core/typeclass/Compactable" -import type { Covariant } from "@fp-ts/core/typeclass/Covariant" -import type { Traversable } from "@fp-ts/core/typeclass/Traversable" - -/** - * @category models - * @since 1.0.0 - */ -export interface TraversableFilterable extends TypeClass { - readonly traversePartitionMap: ( - F: Applicative - ) => ( - f: (a: A) => Kind> - ) => ( - self: Kind - ) => Kind, Kind]> - - readonly traverseFilterMap: ( - F: Applicative - ) => ( - f: (a: A) => Kind> - ) => ( - self: Kind - ) => Kind> -} - -/** - * Returns a default `traversePartitionMap` implementation. - * - * @since 1.0.0 - */ -export const traversePartitionMap = ( - T: Traversable & Covariant & Compactable -): TraversableFilterable["traversePartitionMap"] => - (F) => - f => - ta => - pipe( - ta, - T.traverse(F)(f), - F.map(compactable.separate(T)) - ) - -/** - * Returns a default `traverseFilterMap` implementation. - * - * @since 1.0.0 - */ -export const traverseFilterMap = ( - T: Traversable & Compactable -): TraversableFilterable["traverseFilterMap"] => - (F) => f => ta => pipe(ta, T.traverse(F)(f), F.map(T.compact)) - -/** - * @since 1.0.0 - */ -export const traverseFilter = ( - T: TraversableFilterable -) => - ( - F: Applicative - ): (( - predicate: (a: A) => Kind - ) => ( - self: Kind - ) => Kind>) => - (predicate) => - T.traverseFilterMap(F)(b => - pipe( - predicate(b), - F.map(keep => (keep ? option.some(b) : option.none)) - ) - ) - -/** - * @since 1.0.0 - */ -export const traversePartition = ( - T: TraversableFilterable -) => - ( - F: Applicative - ): (( - predicate: (a: A) => Kind - ) => ( - self: Kind - ) => Kind, Kind]>) => - (predicate) => - T.traversePartitionMap(F)(b => - pipe( - predicate(b), - F.map((keep) => (keep ? either.right(b) : either.left(b))) - ) - ) diff --git a/test/data/Either.ts b/test/data/Either.ts new file mode 100644 index 000000000..643702a48 --- /dev/null +++ b/test/data/Either.ts @@ -0,0 +1,64 @@ +import type { TypeLambda } from "@fp-ts/core/HKT" +import * as covariant from "@fp-ts/core/typeclass/Covariant" +import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" +import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" + +export interface Left { + readonly _tag: "Left" + readonly left: E +} + +export interface Right { + readonly _tag: "Right" + readonly right: A +} + +export type Either = Left | Right + +export interface EitherTypeLambda extends TypeLambda { + readonly type: Either +} + +export const left = (e: E): Either => ({ _tag: "Left", left: e }) + +export const right = (a: A): Either => ({ _tag: "Right", right: a }) + +/** + * @since 1.0.0 + */ +export const isLeft = (self: Either): self is Left => self._tag === "Left" + +/** + * @since 1.0.0 + */ +export const isRight = (self: Either): self is Right => self._tag === "Right" + +const map = (f: (a: A) => B) => + (self: Either): Either => isRight(self) ? right(f(self.right)) : self + +const imap = covariant.imap(map) + +const coproduct = ( + that: Either +) => (self: Either): Either => isRight(self) ? self : that + +export const SemiCoproduct: semiCoproduct.SemiCoproduct = { + imap, + coproduct, + coproductMany: collection => + self => { + let out = self + if (isRight(out)) { + return out + } + for (out of collection) { + if (isRight(out)) { + return out + } + } + return out + } +} + +export const getSemigroup: () => Semigroup> = semiCoproduct + .getSemigroup(SemiCoproduct) diff --git a/test/test-data/NonEmptyArray.ts b/test/data/NonEmptyArray.ts similarity index 100% rename from test/test-data/NonEmptyArray.ts rename to test/data/NonEmptyArray.ts diff --git a/test/test-data/NonEmptyReadonlyArray.ts b/test/data/NonEmptyReadonlyArray.ts similarity index 100% rename from test/test-data/NonEmptyReadonlyArray.ts rename to test/data/NonEmptyReadonlyArray.ts diff --git a/test/test-data/Option.ts b/test/data/Option.ts similarity index 64% rename from test/test-data/Option.ts rename to test/data/Option.ts index fa0ce70bb..37b952948 100644 --- a/test/test-data/Option.ts +++ b/test/data/Option.ts @@ -12,19 +12,14 @@ * * @since 1.0.0 */ -import type { Either } from "@fp-ts/core/data/Either" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" -import * as either from "@fp-ts/core/internal/Either" import type { LazyArg } from "@fp-ts/core/internal/Function" import { identity, pipe } from "@fp-ts/core/internal/Function" -import * as option from "@fp-ts/core/internal/Option" import type * as extendable from "@fp-ts/core/test/limbo/Extendable" import type * as alternative from "@fp-ts/core/typeclass/Alternative" import type * as applicative from "@fp-ts/core/typeclass/Applicative" import * as chainable from "@fp-ts/core/typeclass/Chainable" -import type * as compactable from "@fp-ts/core/typeclass/Compactable" import * as covariant from "@fp-ts/core/typeclass/Covariant" -import * as filterable from "@fp-ts/core/typeclass/Filterable" import * as flatMap_ from "@fp-ts/core/typeclass/FlatMap" import type * as foldable from "@fp-ts/core/typeclass/Foldable" import * as invariant from "@fp-ts/core/typeclass/Invariant" @@ -40,98 +35,33 @@ import type * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" import type * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as semiProduct from "@fp-ts/core/typeclass/SemiProduct" import * as traversable from "@fp-ts/core/typeclass/Traversable" -import * as traversableFilterable from "@fp-ts/core/typeclass/TraversableFilterable" import type * as foldableWithIndex from "../limbo/FoldableWithIndex" import * as nonEmptyArray from "./NonEmptyArray" import * as nonEmptyReadonlyArray from "./NonEmptyReadonlyArray" -/** - * @category models - * @since 1.0.0 - */ export interface None { readonly _tag: "None" } -/** - * @category models - * @since 1.0.0 - */ export interface Some { readonly _tag: "Some" readonly value: A } -/** - * @category models - * @since 1.0.0 - */ export type Option = None | Some -// ------------------------------------------------------------------------------------- -// type lambdas -// ------------------------------------------------------------------------------------- - -/** - * @category type lambdas - * @since 1.0.0 - */ export interface OptionTypeLambda extends TypeLambda { readonly type: Option } -// ------------------------------------------------------------------------------------- -// refinements -// ------------------------------------------------------------------------------------- +export const isNone = (fa: Option): fa is None => fa._tag === "None" -/** - * Returns `true` if the option is `None`, `false` otherwise. - * - * @exampleTodo - * import { some, none, isNone } from '@fp-ts/data/Option' - * - * assert.strictEqual(isNone(some(1)), false) - * assert.strictEqual(isNone(none), true) - * - * @category refinements - * @since 1.0.0 - */ -export const isNone: (fa: Option) => fa is None = option.isNone +export const isSome = (fa: Option): fa is Some => fa._tag === "Some" -/** - * Returns `true` if the option is an instance of `Some`, `false` otherwise. - * - * @exampleTodo - * import { some, none, isSome } from '@fp-ts/data/Option' - * - * assert.strictEqual(isSome(some(1)), true) - * assert.strictEqual(isSome(none), false) - * - * @category refinements - * @since 1.0.0 - */ -export const isSome: (fa: Option) => fa is Some = option.isSome - -/** - * `None` doesn't have a constructor, instead you can use it directly as a value. Represents a missing value. - * - * @category constructors - * @since 1.0.0 - */ -export const none: Option = option.none +export const none: Option = { _tag: "None" } -/** - * Constructs a `Some`. Represents an optional value that exists. - * - * @category constructors - * @since 1.0.0 - */ -export const some: (a: A) => Option = option.some +export const some = (a: A): Option => ({ _tag: "Some", value: a }) -/** - * @category conversions - * @since 1.0.0 - */ export const fromIterable = (collection: Iterable): Option => { for (const a of collection) { return some(a) @@ -139,98 +69,12 @@ export const fromIterable = (collection: Iterable): Option => { return none } -/** - * Converts a `Result` to an `Option` discarding the error. - * - * @exampleTodo - * import * as O from '@fp-ts/data/Option' - * import * as R from '@fp-ts/data/Result' - * - * assert.deepStrictEqual(O.fromResult(R.succeed(1)), O.some(1)) - * assert.deepStrictEqual(O.fromResult(R.fail('a')), O.none) - * - * @category conversions - * @since 1.0.0 - */ -export const fromEither: (self: Either) => Option = either.getRight - -/** - * Takes a (lazy) default value, a function, and an `Option` value, if the `Option` value is `None` the default value is - * returned, otherwise the function is applied to the value inside the `Some` and the result is returned. - * - * @exampleTodo - * import { some, none, match } from '@fp-ts/data/Option' - * import { pipe } from '@fp-ts/data/Function' - * - * assert.strictEqual( - * pipe( - * some(1), - * match(() => 'a none', a => `a some containing ${a}`) - * ), - * 'a some containing 1' - * ) - * - * assert.strictEqual( - * pipe( - * none, - * match(() => 'a none', a => `a some containing ${a}`) - * ), - * 'a none' - * ) - * - * @category pattern matching - * @since 1.0.0 - */ export const match = (onNone: LazyArg, onSome: (a: A) => C) => (ma: Option): B | C => isNone(ma) ? onNone() : onSome(ma.value) -/** - * Extracts the value out of the structure, if it exists. Otherwise returns the given default value - * - * @exampleTodo - * import { some, none, getOrElse } from '@fp-ts/data/Option' - * import { pipe } from '@fp-ts/data/Function' - * - * assert.strictEqual( - * pipe( - * some(1), - * getOrElse(0) - * ), - * 1 - * ) - * assert.strictEqual( - * pipe( - * none, - * getOrElse(0) - * ), - * 0 - * ) - * - * @category error handling - * @since 1.0.0 - */ export const getOrElse = (onNone: B) => (ma: Option): A | B => isNone(ma) ? onNone : ma.value -/** - * Converts an exception into an `Option`. If `f` throws, returns `None`, otherwise returns the output wrapped in a - * `Some`. - * - * @exampleTodo - * import { none, some, fromThrowable } from '@fp-ts/data/Option' - * - * assert.deepStrictEqual( - * fromThrowable(() => { - * throw new Error() - * }), - * none - * ) - * assert.deepStrictEqual(fromThrowable(() => 1), some(1)) - * - * @category interop - * @see {@link liftThrowable} - * @since 1.0.0 - */ export const fromThrowable = (f: () => A): Option => { try { return some(f()) @@ -239,41 +83,10 @@ export const fromThrowable = (f: () => A): Option => { } } -/** - * Lifts a function that may throw to one returning a `Option`. - * - * @category interop - * @since 1.0.0 - */ export const liftThrowable = , B>( f: (...a: A) => B ): ((...a: A) => Option) => (...a) => fromThrowable(() => f(...a)) -/** - * Extracts the value out of the structure, if it exists. Otherwise returns `null`. - * - * @exampleTodo - * import { some, none, toNull } from '@fp-ts/data/Option' - * import { pipe } from '@fp-ts/data/Function' - * - * assert.strictEqual( - * pipe( - * some(1), - * toNull - * ), - * 1 - * ) - * assert.strictEqual( - * pipe( - * none, - * toNull - * ), - * null - * ) - * - * @category conversions - * @since 1.0.0 - */ export const toNull: (self: Option) => A | null = getOrElse(null) /** @@ -472,15 +285,6 @@ export const duplicate: (ma: Option) => Option> = extend(identit */ export const compact: (foa: Option>) => Option = flatten -const defaultSeparated = [none, none] as const - -/** - * @category filtering - * @since 1.0.0 - */ -export const separate: (fe: Option>) => readonly [Option, Option] = (ma) => - isNone(ma) ? defaultSeparated : [either.getLeft(ma.value), fromEither(ma.value)] - /** * @category filtering * @since 1.0.0 @@ -488,14 +292,6 @@ export const separate: (fe: Option>) => readonly [Option, export const filterMap: (f: (a: A) => Option) => (fa: Option) => Option = (f) => (fa) => isNone(fa) ? none : f(fa.value) -/** - * @category filtering - * @since 1.0.0 - */ -export const partitionMap: ( - f: (a: A) => Either -) => (fa: Option) => readonly [Option, Option] = (f) => oa => pipe(oa, map(f), separate) - /** * @category traversing * @since 1.0.0 @@ -810,44 +606,6 @@ export const Extendable: extendable.Extendable = { extend } -/** - * @category instances - * @since 1.0.0 - */ -export const Compactable: compactable.Compactable = { - compact -} - -/** - * @category instances - * @since 1.0.0 - */ -export const Filterable: filterable.Filterable = { - filterMap -} - -/** - * @category filtering - * @since 1.0.0 - */ -export const filter: { - (refinement: (a: A) => a is B): (fc: Option) => Option - (predicate: (a: A) => boolean): (fb: Option) => Option -} = filterable.filter(Filterable) - -/** - * @category filtering - * @since 1.0.0 - */ -export const partition: { - ( - refinement: (a: A) => a is B - ): (fc: Option) => readonly [Option, Option] - ( - predicate: (a: A) => boolean - ): (fb: Option) => readonly [Option, Option] -} = filterable.partition(Filterable) - /** * @category traversing * @since 1.0.0 @@ -866,165 +624,9 @@ export const Traversable: traversable.Traversable = { sequence } -/** - * @category filtering - * @since 1.0.0 - */ -export const traverseFilterMap: ( - Applicative: applicative.Applicative -) => ( - f: (a: A) => Kind> -) => (ta: Option) => Kind> = traversableFilterable.traverseFilterMap( - { ...Traversable, ...Compactable } -) - -/** - * @category filtering - * @since 1.0.0 - */ -export const traversePartitionMap: ( - Applicative: applicative.Applicative -) => ( - f: (a: A) => Kind> -) => (wa: Option) => Kind, Option]> = traversableFilterable - .traversePartitionMap({ ...Traversable, ...Covariant, ...Compactable }) - -/** - * @category instances - * @since 1.0.0 - */ -export const TraversableFilterable: traversableFilterable.TraversableFilterable< - OptionTypeLambda -> = { - traverseFilterMap, - traversePartitionMap -} - -/** - * @category filtering - * @since 1.0.0 - */ -export const traverseFilter: ( - Applicative: applicative.Applicative -) => ( - predicate: (a: A) => Kind -) => (self: Option) => Kind> = traversableFilterable.traverseFilter( - TraversableFilterable -) - -/** - * @category filtering - * @since 1.0.0 - */ -export const traversePartition: ( - Applicative: applicative.Applicative -) => ( - predicate: (a: A) => Kind -) => (self: Option) => Kind, Option]> = traversableFilterable - .traversePartition(TraversableFilterable) - -// TODO -// /** -// * Returns a *smart constructor* based on the given predicate. -// * -// * @exampleTodo -// * import * as O from '@fp-ts/data/Option' -// * -// * const getOption = O.liftPredicate((n: number) => n >= 0) -// * -// * assert.deepStrictEqual(getOption(-1), O.none) -// * assert.deepStrictEqual(getOption(1), O.some(1)) -// * -// * @category lifting -// * @since 1.0.0 -// */ -// export const liftPredicate: { -// (refinement: Refinement): (c: C) => Option -// (predicate: Predicate): (b: B) => Option -// } = fromOption_.liftPredicate(FromOption) - -// TODO -// /** -// * @category instances -// * @since 1.0.0 -// */ -// export const FromResult: fromResult_.FromResult = { -// fromResult: fromEither -// } - -// TODO -// /** -// * @category lifting -// * @since 1.0.0 -// */ -// export const liftResult: , E, B>( -// f: (...a: A) => Result -// ) => (...a: A) => Option = fromResult_.liftResult(FromResult) - -// TODO -// /** -// * @category sequencing -// * @since 1.0.0 -// */ -// export const flatMapResult: (f: (a: A) => Result) => (ma: Option) => Option = -// fromResult_.flatMapResult(FromResult, FlatMap) - -// TODO -// /** -// * Tests whether a value is a member of a `Option`. -// * -// * @exampleTodo -// * import * as O from '@fp-ts/data/Option' -// * import * as N from '@fp-ts/data/number' -// * import { pipe } from '@fp-ts/data/Function' -// * -// * assert.strictEqual(pipe(O.some(1), O.elem(N.Eq)(1)), true) -// * assert.strictEqual(pipe(O.some(1), O.elem(N.Eq)(2)), false) -// * assert.strictEqual(pipe(O.none, O.elem(N.Eq)(1)), false) -// * -// * @since 1.0.0 -// */ -// export const elem = (a: A) => -// (ma: Option): boolean => isNone(ma) ? false : equals(ma.value)(a) - -/** - * Returns `true` if the predicate is satisfied by the wrapped value - * - * @exampleTodo - * import { some, none, exists } from '@fp-ts/data/Option' - * import { pipe } from '@fp-ts/data/Function' - * - * assert.strictEqual( - * pipe( - * some(1), - * exists(n => n > 0) - * ), - * true - * ) - * assert.strictEqual( - * pipe( - * some(1), - * exists(n => n > 1) - * ), - * false - * ) - * assert.strictEqual( - * pipe( - * none, - * exists(n => n > 0) - * ), - * false - * ) - * - * @since 1.0.0 - */ export const exists = (predicate: (a: A) => boolean) => (ma: Option): boolean => isNone(ma) ? false : predicate(ma.value) -// ------------------------------------------------------------------------------------- -// do notation -// ------------------------------------------------------------------------------------- - /** * @category do notation * @since 1.0.0 diff --git a/test/test-data/Predicate.ts b/test/data/Predicate.ts similarity index 100% rename from test/test-data/Predicate.ts rename to test/data/Predicate.ts diff --git a/test/test-data/ReadonlyArray.ts b/test/data/ReadonlyArray.ts similarity index 78% rename from test/test-data/ReadonlyArray.ts rename to test/data/ReadonlyArray.ts index 9413cb09a..a11bea077 100644 --- a/test/test-data/ReadonlyArray.ts +++ b/test/data/ReadonlyArray.ts @@ -1,6 +1,4 @@ -import type { compactable, filterable } from "@fp-ts/core" -import { semiProduct, traversableFilterable } from "@fp-ts/core" -import type { Option } from "@fp-ts/core/data/Option" +import { semiProduct } from "@fp-ts/core" import type { Kind, TypeLambda } from "@fp-ts/core/HKT" import { identity, pipe } from "@fp-ts/core/internal/Function" import type * as applicative from "@fp-ts/core/typeclass/Applicative" @@ -11,12 +9,12 @@ import type { Order } from "@fp-ts/core/typeclass/Order" import type * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import type * as traverse_ from "@fp-ts/core/typeclass/Traversable" import type * as covariantWithIndex from "../limbo/CovariantWithIndex" -import * as filterableWithIndex from "../limbo/FilterableWithIndex" import * as foldableWithIndex from "../limbo/FoldableWithIndex" import type * as traversableWithIndex from "../limbo/TraversableWithIndex" import type { NonEmptyReadonlyArray } from "./NonEmptyReadonlyArray" import * as nonEmptyReadonlyArray from "./NonEmptyReadonlyArray" import * as O from "./Option" +import type { Option } from "./Option" export interface ReadonlyArrayTypeLambda extends TypeLambda { readonly type: ReadonlyArray @@ -150,51 +148,3 @@ export const filterMapWithIndex = (f: (a: A, i: number) => Option) => } return out } - -export const FilterableWithIndex: filterableWithIndex.FilterableWithIndex< - ReadonlyArrayTypeLambda, - number -> = { - filterMapWithIndex -} - -export const filterMap: ( - f: (a: A) => Option -) => (fa: ReadonlyArray) => ReadonlyArray = filterableWithIndex.filterMap(FilterableWithIndex) - -export const compact: (fa: ReadonlyArray>) => ReadonlyArray = - /*#__PURE__*/ filterMap(identity) - -export const Compactable: compactable.Compactable = { - compact -} - -export const Filterable: filterable.Filterable = { - filterMap -} - -/** - * @category filtering - * @since 1.0.0 - */ -export const traverseFilterMap = traversableFilterable.traverseFilterMap( - { ...Traversable, ...Compactable } -) - -/** - * @category filtering - * @since 1.0.0 - */ -export const traversePartitionMap = traversableFilterable - .traversePartitionMap({ ...Traversable, ...Covariant, ...Compactable }) - -/** - * @category instances - * @since 1.0.0 - */ -export const TraversableFilterable: traversableFilterable.TraversableFilterable< - ReadonlyArrayTypeLambda -> = { - traverseFilterMap, - traversePartitionMap -} diff --git a/test/test-data/boolean.ts b/test/data/boolean.ts similarity index 100% rename from test/test-data/boolean.ts rename to test/data/boolean.ts diff --git a/test/test-data/number.ts b/test/data/number.ts similarity index 100% rename from test/test-data/number.ts rename to test/data/number.ts diff --git a/test/test-data/string.ts b/test/data/string.ts similarity index 100% rename from test/test-data/string.ts rename to test/data/string.ts diff --git a/test/internal/Either.ts b/test/internal/Either.ts deleted file mode 100644 index 2a171f52f..000000000 --- a/test/internal/Either.ts +++ /dev/null @@ -1,14 +0,0 @@ -import * as _ from "@fp-ts/core/internal/Either" -import * as U from "../util" - -describe("Either", () => { - it("isRight", () => { - U.deepStrictEqual(_.isRight(_.right(1)), true) - U.deepStrictEqual(_.isRight(_.left("e")), false) - }) - - it("isLeft", () => { - U.deepStrictEqual(_.isLeft(_.right(1)), false) - U.deepStrictEqual(_.isLeft(_.left("e")), true) - }) -}) diff --git a/test/limbo/FilterableWithIndex.ts b/test/limbo/FilterableWithIndex.ts deleted file mode 100644 index 4a08506ce..000000000 --- a/test/limbo/FilterableWithIndex.ts +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @since 1.0.0 - */ -import type { Either } from "@fp-ts/core/data/Either" -import type { Option } from "@fp-ts/core/data/Option" -import type { Kind, TypeClass, TypeLambda } from "@fp-ts/core/HKT" -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" -import * as option from "@fp-ts/core/internal/Option" -import type { Covariant } from "@fp-ts/core/typeclass/Covariant" -import type { Filterable } from "@fp-ts/core/typeclass/Filterable" - -/** - * @category models - * @since 1.0.0 - */ -export interface FilterableWithIndex extends TypeClass { - readonly filterMapWithIndex: ( - f: (a: A, i: I) => Option - ) => (self: Kind) => Kind -} - -/** - * Returns a default `filterMapWithIndex` composition. - * - * @since 1.0.0 - */ -export const filterMapWithIndexComposition = ( - F: Covariant, - G: FilterableWithIndex -) => - ( - f: (a: A, i: I) => Option - ): ( - self: Kind> - ) => Kind> => F.map(G.filterMapWithIndex(f)) - -/** - * Returns a default `filterMap` implementation. - * - * @since 1.0.0 - */ -export const filterMap = ( - F: FilterableWithIndex -): Filterable["filterMap"] => (f) => F.filterMapWithIndex(f) - -/** - * @since 1.0.0 - */ -export const filterWithIndex: ( - F: FilterableWithIndex -) => { - (refinement: (a: A, i: I) => a is B): ( - self: Kind - ) => Kind - ( - predicate: (a: A, i: I) => boolean - ): (self: Kind) => Kind -} = (FilterableWithIndex: FilterableWithIndex) => - ( - predicate: (a: A, i: I) => boolean - ): ((self: Kind) => Kind) => - FilterableWithIndex.filterMapWithIndex(( - b, - i - ) => (predicate(b, i) ? option.some(b) : option.none)) - -/** - * @since 1.0.0 - */ -export const partitionMapWithIndex = ( - F: FilterableWithIndex -) => - (f: (a: A, i: I) => Either) => - ( - self: Kind - ): readonly [Kind, Kind] => { - return [ - pipe(self, F.filterMapWithIndex((a, i) => either.getLeft(f(a, i)))), - pipe(self, F.filterMapWithIndex((a, i) => either.getRight(f(a, i)))) - ] - } - -/** - * @since 1.0.0 - */ -export const partitionWithIndex: ( - F: FilterableWithIndex -) => { - (refinement: (a: A, i: I) => a is B): ( - self: Kind - ) => readonly [Kind, Kind] - (predicate: (a: A, i: I) => boolean): ( - self: Kind - ) => readonly [Kind, Kind] -} = (FilterableWithIndex: FilterableWithIndex) => { - const partitionMapWithIndex_ = partitionMapWithIndex(FilterableWithIndex) - return ( - predicate: (a: A, i: I) => boolean - ): (( - self: Kind - ) => readonly [Kind, Kind]) => - partitionMapWithIndex_((b, i) => (predicate(b, i) ? either.right(b) : either.left(b))) -} diff --git a/test/test-data/Either.ts b/test/test-data/Either.ts deleted file mode 100644 index 048828d60..000000000 --- a/test/test-data/Either.ts +++ /dev/null @@ -1,39 +0,0 @@ -import type { Either, EitherTypeLambda } from "@fp-ts/core/data/Either" -import * as either from "@fp-ts/core/internal/Either" -import * as covariant from "@fp-ts/core/typeclass/Covariant" -import * as semiCoproduct from "@fp-ts/core/typeclass/SemiCoproduct" -import type { Semigroup } from "@fp-ts/core/typeclass/Semigroup" - -export const right = either.right - -export const left = either.left - -const map = (f: (a: A) => B) => - (self: Either): Either => either.isRight(self) ? right(f(self.right)) : self - -const imap = covariant.imap(map) - -const coproduct = ( - that: Either -) => (self: Either): Either => either.isRight(self) ? self : that - -export const SemiCoproduct: semiCoproduct.SemiCoproduct = { - imap, - coproduct, - coproductMany: collection => - self => { - let out = self - if (either.isRight(out)) { - return out - } - for (out of collection) { - if (either.isRight(out)) { - return out - } - } - return out - } -} - -export const getSemigroup: () => Semigroup> = semiCoproduct - .getSemigroup(SemiCoproduct) diff --git a/test/typeclass/Applicative.ts b/test/typeclass/Applicative.ts index 46d4c5da5..97e5610d5 100644 --- a/test/typeclass/Applicative.ts +++ b/test/typeclass/Applicative.ts @@ -1,7 +1,7 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Applicative" -import * as N from "../test-data/number" -import * as O from "../test-data/Option" +import * as N from "../data/number" +import * as O from "../data/Option" import * as U from "../util" describe("Applicative", () => { diff --git a/test/typeclass/Bicovariant.ts b/test/typeclass/Bicovariant.ts index fc6799c33..712cf4352 100644 --- a/test/typeclass/Bicovariant.ts +++ b/test/typeclass/Bicovariant.ts @@ -1,8 +1,8 @@ -import type { EitherTypeLambda } from "@fp-ts/core/data/Either" -import * as E from "@fp-ts/core/internal/Either" import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Bicovariant" -import * as RA from "../test-data/ReadonlyArray" +import type { EitherTypeLambda } from "../data/Either" +import * as E from "../data/Either" +import * as RA from "../data/ReadonlyArray" import * as U from "../util" export const Bicovariant: _.Bicovariant = { diff --git a/test/typeclass/Bounded.ts b/test/typeclass/Bounded.ts index a39428177..7c02285dc 100644 --- a/test/typeclass/Bounded.ts +++ b/test/typeclass/Bounded.ts @@ -1,5 +1,5 @@ import * as _ from "@fp-ts/core/typeclass/Bounded" -import * as number from "../test-data/number" +import * as number from "../data/number" import * as U from "../util" describe("Bounded", () => { diff --git a/test/typeclass/Chainable.ts b/test/typeclass/Chainable.ts index bd46997de..4fffd748f 100644 --- a/test/typeclass/Chainable.ts +++ b/test/typeclass/Chainable.ts @@ -1,6 +1,6 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Chainable" -import * as O from "../test-data/Option" +import * as O from "../data/Option" import * as U from "../util" describe("Chainable", () => { diff --git a/test/typeclass/Compactable.ts b/test/typeclass/Compactable.ts deleted file mode 100644 index 737a16b35..000000000 --- a/test/typeclass/Compactable.ts +++ /dev/null @@ -1,25 +0,0 @@ -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" -import * as _ from "@fp-ts/core/typeclass/Compactable" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" -import * as U from "../util" - -describe("Compactable", () => { - it("compactComposition", () => { - const compact = _.compactComposition(RA.Covariant, O.Compactable) - U.deepStrictEqual(pipe([], compact), []) - U.deepStrictEqual(pipe([O.none], compact), [O.none]) - U.deepStrictEqual(pipe([O.some(O.none)], compact), [O.none]) - U.deepStrictEqual(pipe([O.some(O.some(1))], compact), [O.some(1)]) - }) - - it("separate", () => { - const separate = _.separate({ ...RA.Covariant, ...RA.Compactable }) - U.deepStrictEqual(pipe([], separate), [[], []]) - U.deepStrictEqual(pipe([either.right(1), either.left("e"), either.right(2)], separate), [ - ["e"], - [1, 2] - ]) - }) -}) diff --git a/test/typeclass/Contravariant.ts b/test/typeclass/Contravariant.ts index 271ad07aa..a843e650b 100644 --- a/test/typeclass/Contravariant.ts +++ b/test/typeclass/Contravariant.ts @@ -1,8 +1,8 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Contravariant" import * as order from "@fp-ts/core/typeclass/Order" -import * as P from "../test-data/Predicate" -import * as string from "../test-data/string" +import * as P from "../data/Predicate" +import * as string from "../data/string" import * as U from "../util" describe("Contravariant", () => { diff --git a/test/typeclass/Coproduct.ts b/test/typeclass/Coproduct.ts index a32a34266..2bc212210 100644 --- a/test/typeclass/Coproduct.ts +++ b/test/typeclass/Coproduct.ts @@ -1,6 +1,6 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Coproduct" -import * as O from "../test-data/Option" +import * as O from "../data/Option" import * as U from "../util" describe("Coproduct", () => { diff --git a/test/typeclass/Covariant.ts b/test/typeclass/Covariant.ts index e713ab533..e2be796ff 100644 --- a/test/typeclass/Covariant.ts +++ b/test/typeclass/Covariant.ts @@ -1,7 +1,7 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Covariant" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" +import * as O from "../data/Option" +import * as RA from "../data/ReadonlyArray" import * as U from "../util" describe("Covariant", () => { diff --git a/test/typeclass/CovariantWithIndex.ts b/test/typeclass/CovariantWithIndex.ts index 4f7a288c4..c2f630bfb 100644 --- a/test/typeclass/CovariantWithIndex.ts +++ b/test/typeclass/CovariantWithIndex.ts @@ -1,6 +1,6 @@ import { pipe } from "@fp-ts/core/internal/Function" +import * as RA from "../data/ReadonlyArray" import * as _ from "../limbo/CovariantWithIndex" -import * as RA from "../test-data/ReadonlyArray" import * as U from "../util" describe("FunctorWithIndex", () => { diff --git a/test/typeclass/Filterable.ts b/test/typeclass/Filterable.ts deleted file mode 100644 index ae957adec..000000000 --- a/test/typeclass/Filterable.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" -import * as _ from "@fp-ts/core/typeclass/Filterable" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" -import * as U from "../util" - -describe("Filterable", () => { - it("filterMapComposition", () => { - const filterMap = _.filterMapComposition(RA.Covariant, O.Filterable) - const f = filterMap((s: string) => s.length > 1 ? O.some(s.length) : O.none) - U.deepStrictEqual(pipe([], f), []) - U.deepStrictEqual(pipe([O.none], f), [O.none]) - U.deepStrictEqual(pipe([O.some("a")], f), [O.none]) - U.deepStrictEqual(pipe([O.some("aa")], f), [O.some(2)]) - }) - - it("filter", () => { - const filter = _.filter(RA.Filterable) - const f = filter((n: number) => n > 0) - U.deepStrictEqual(pipe([], f), []) - U.deepStrictEqual(pipe([1], f), [1]) - U.deepStrictEqual(pipe([-1], f), []) - U.deepStrictEqual(pipe([1, -1], f), [1]) - }) - - it("partitionMap", () => { - const partitionMap = _.partitionMap(RA.Filterable) - const f = partitionMap((s: string) => s.length > 1 ? either.right(s.length) : either.left(s)) - U.deepStrictEqual(pipe([], f), [[], []]) - U.deepStrictEqual(pipe(["a"], f), [["a"], []]) - U.deepStrictEqual(pipe(["aa"], f), [[], [2]]) - U.deepStrictEqual(pipe(["aa", "a"], f), [["a"], [2]]) - }) - - it("partition", () => { - const partition = _.partition(RA.Filterable) - const f = partition((n: number) => n > 0) - U.deepStrictEqual(pipe([], f), [[], []]) - U.deepStrictEqual(pipe([1], f), [[], [1]]) - U.deepStrictEqual(pipe([-1], f), [[-1], []]) - U.deepStrictEqual(pipe([1, -1], f), [[-1], [1]]) - }) -}) diff --git a/test/typeclass/FilterableWithIndex.ts b/test/typeclass/FilterableWithIndex.ts deleted file mode 100644 index 4255eceef..000000000 --- a/test/typeclass/FilterableWithIndex.ts +++ /dev/null @@ -1,55 +0,0 @@ -import * as either from "@fp-ts/core/internal/Either" -import { pipe } from "@fp-ts/core/internal/Function" -import * as _ from "../limbo/FilterableWithIndex" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" -import * as U from "../util" - -describe("FilterableWithIndex", () => { - it("filterMapWithIndexComposition", () => { - const filterMapWithIndex = _.filterMapWithIndexComposition(RA.Covariant, RA.FilterableWithIndex) - const f = filterMapWithIndex((s: string, i: number) => - s.length > 1 ? O.some(s.length + i) : O.none - ) - U.deepStrictEqual(pipe([], f), []) - U.deepStrictEqual(pipe([["a"]], f), [[]]) - U.deepStrictEqual(pipe([["aa"]], f), [[2]]) - U.deepStrictEqual(pipe([["aa"], ["b"]], f), [[2], []]) - U.deepStrictEqual(pipe([["aa"], ["bb"]], f), [[2], [2]]) - U.deepStrictEqual(pipe([["a", "aa"], ["bb"]], f), [[3], [2]]) - }) - - it("filterWithIndex", () => { - const filterWithIndex = _.filterWithIndex(RA.FilterableWithIndex) - const f = filterWithIndex((n: number, i: number) => n + i > 0) - U.deepStrictEqual(pipe([], f), []) - U.deepStrictEqual(pipe([1], f), [1]) - U.deepStrictEqual(pipe([-1], f), []) - U.deepStrictEqual(pipe([1, -1], f), [1]) - U.deepStrictEqual(pipe([1, 0], f), [1, 0]) - }) - - it("partitionMapWithIndex", () => { - const partitionMapWithIndex = _.partitionMapWithIndex(RA.FilterableWithIndex) - const f = partitionMapWithIndex((s: string, i: number) => - s.length > 1 ? either.right(s.length + i) : either.left(s) - ) - U.deepStrictEqual(pipe([], f), [[], []]) - U.deepStrictEqual(pipe(["a"], f), [["a"], []]) - U.deepStrictEqual(pipe(["aa"], f), [[], [2]]) - U.deepStrictEqual(pipe(["aa", "b"], f), [["b"], [2]]) - U.deepStrictEqual(pipe(["aa", "bbb"], f), [[], [2, 4]]) - U.deepStrictEqual(pipe(["aa", "a"], f), [["a"], [2]]) - U.deepStrictEqual(pipe(["a", "aa", "bbb"], f), [["a"], [3, 5]]) - }) - - it("partitionWithIndex", () => { - const partitionWithIndex = _.partitionWithIndex(RA.FilterableWithIndex) - const f = partitionWithIndex((n: number, i: number) => n + i > 0) - U.deepStrictEqual(pipe([], f), [[], []]) - U.deepStrictEqual(pipe([1], f), [[], [1]]) - U.deepStrictEqual(pipe([-1], f), [[-1], []]) - U.deepStrictEqual(pipe([1, -1], f), [[-1], [1]]) - U.deepStrictEqual(pipe([1, 0], f), [[], [1, 0]]) - }) -}) diff --git a/test/typeclass/FlatMap.ts b/test/typeclass/FlatMap.ts index c0de5c107..331606b5b 100644 --- a/test/typeclass/FlatMap.ts +++ b/test/typeclass/FlatMap.ts @@ -1,6 +1,6 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/FlatMap" -import * as O from "../test-data/Option" +import * as O from "../data/Option" import * as U from "../util" describe("FlatMap", () => { diff --git a/test/typeclass/Foldable.ts b/test/typeclass/Foldable.ts index 2cea599ae..4c0285898 100644 --- a/test/typeclass/Foldable.ts +++ b/test/typeclass/Foldable.ts @@ -1,8 +1,8 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Foldable" -import * as number from "../test-data/number" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" +import * as number from "../data/number" +import * as O from "../data/Option" +import * as RA from "../data/ReadonlyArray" import * as U from "../util" describe("Foldable", () => { diff --git a/test/typeclass/FoldableWithIndex.ts b/test/typeclass/FoldableWithIndex.ts index 221eb2010..b1ef8a1af 100644 --- a/test/typeclass/FoldableWithIndex.ts +++ b/test/typeclass/FoldableWithIndex.ts @@ -1,8 +1,8 @@ import { pipe } from "@fp-ts/core/internal/Function" +import * as number from "../data/number" +import * as O from "../data/Option" +import * as RA from "../data/ReadonlyArray" import * as foldableWithIndex from "../limbo/FoldableWithIndex" -import * as number from "../test-data/number" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" import * as U from "../util" describe("FoldableWithIndex", () => { diff --git a/test/typeclass/Invariant.ts b/test/typeclass/Invariant.ts index 7c4d67ec6..2c20678b1 100644 --- a/test/typeclass/Invariant.ts +++ b/test/typeclass/Invariant.ts @@ -1,9 +1,9 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Invariant" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" -import * as O from "../test-data/Option" -import * as P from "../test-data/Predicate" -import * as string from "../test-data/string" +import * as O from "../data/Option" +import * as P from "../data/Predicate" +import * as string from "../data/string" import * as U from "../util" describe("Invariant", () => { diff --git a/test/typeclass/Monoid.ts b/test/typeclass/Monoid.ts index 2581d492f..22a22d5b8 100644 --- a/test/typeclass/Monoid.ts +++ b/test/typeclass/Monoid.ts @@ -1,7 +1,7 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as monoid from "@fp-ts/core/typeclass/Monoid" -import * as number from "../test-data/number" -import * as string from "../test-data/string" +import * as number from "../data/number" +import * as string from "../data/string" import * as U from "../util" describe("Monoid", () => { diff --git a/test/typeclass/NonEmptyTraversable.ts b/test/typeclass/NonEmptyTraversable.ts index 8933a7175..ce901b412 100644 --- a/test/typeclass/NonEmptyTraversable.ts +++ b/test/typeclass/NonEmptyTraversable.ts @@ -1,6 +1,6 @@ import * as _ from "@fp-ts/core/typeclass/NonEmptyTraversable" -import * as NERA from "../test-data/NonEmptyReadonlyArray" -import * as O from "../test-data/Option" +import * as NERA from "../data/NonEmptyReadonlyArray" +import * as O from "../data/Option" import * as U from "../util" describe("NonEmptyTraversable", () => { diff --git a/test/typeclass/Of.ts b/test/typeclass/Of.ts index c02b12997..8fb357fdd 100644 --- a/test/typeclass/Of.ts +++ b/test/typeclass/Of.ts @@ -1,6 +1,6 @@ import * as _ from "@fp-ts/core/typeclass/Of" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" +import * as O from "../data/Option" +import * as RA from "../data/ReadonlyArray" import * as U from "../util" describe("Of", () => { diff --git a/test/typeclass/Order.ts b/test/typeclass/Order.ts index 2d95857e9..e24e4f0d6 100644 --- a/test/typeclass/Order.ts +++ b/test/typeclass/Order.ts @@ -1,9 +1,9 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Order" -import * as boolean from "../test-data/boolean" -import * as number from "../test-data/number" -import { sort } from "../test-data/ReadonlyArray" -import * as string from "../test-data/string" +import * as boolean from "../data/boolean" +import * as number from "../data/number" +import { sort } from "../data/ReadonlyArray" +import * as string from "../data/string" import * as U from "../util" describe("Order", () => { diff --git a/test/typeclass/Product.ts b/test/typeclass/Product.ts index e566043cb..787a127b6 100644 --- a/test/typeclass/Product.ts +++ b/test/typeclass/Product.ts @@ -1,10 +1,10 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Product" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" -import * as number from "../test-data/number" -import * as O from "../test-data/Option" -import * as P from "../test-data/Predicate" -import * as string from "../test-data/string" +import * as number from "../data/number" +import * as O from "../data/Option" +import * as P from "../data/Predicate" +import * as string from "../data/string" import * as U from "../util" describe("Product", () => { diff --git a/test/typeclass/SemiApplicative.ts b/test/typeclass/SemiApplicative.ts index 617212ad5..a5ed18cc2 100644 --- a/test/typeclass/SemiApplicative.ts +++ b/test/typeclass/SemiApplicative.ts @@ -1,7 +1,7 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/SemiApplicative" -import * as O from "../test-data/Option" -import * as string from "../test-data/string" +import * as O from "../data/Option" +import * as string from "../data/string" import * as U from "../util" describe("SemiApplicative", () => { diff --git a/test/typeclass/SemiCoproduct.ts b/test/typeclass/SemiCoproduct.ts index dbacea187..3692c8384 100644 --- a/test/typeclass/SemiCoproduct.ts +++ b/test/typeclass/SemiCoproduct.ts @@ -1,19 +1,9 @@ -import { left, right } from "@fp-ts/core/internal/Either" import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/SemiCoproduct" -import * as E from "../test-data/Either" -import * as O from "../test-data/Option" +import * as E from "../data/Either" import * as U from "../util" describe("SemiCoproduct", () => { - it("coproductEither", () => { - const coproductEither = _.coproductEither(O.SemiCoproduct) - U.deepStrictEqual(pipe(O.none, coproductEither(O.none)), O.none) - U.deepStrictEqual(pipe(O.none, coproductEither(O.some("a"))), O.some(right("a"))) - U.deepStrictEqual(pipe(O.some(1), coproductEither(O.none)), O.some(left(1))) - U.deepStrictEqual(pipe(O.some(1), coproductEither(O.some("a"))), O.some(left(1))) - }) - it("getSemigroup", () => { const S = _.getSemigroup(E.SemiCoproduct)() U.deepStrictEqual(pipe(E.right(1), S.combine(E.right(2))), E.right(1)) diff --git a/test/typeclass/SemiProduct.ts b/test/typeclass/SemiProduct.ts index cff9a9eea..3f708d7ee 100644 --- a/test/typeclass/SemiProduct.ts +++ b/test/typeclass/SemiProduct.ts @@ -3,11 +3,11 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as semiApplicative from "@fp-ts/core/typeclass/SemiApplicative" import * as semigroup from "@fp-ts/core/typeclass/Semigroup" import * as _ from "@fp-ts/core/typeclass/SemiProduct" -import * as number from "../test-data/number" -import * as O from "../test-data/Option" -import * as P from "../test-data/Predicate" -import * as RA from "../test-data/ReadonlyArray" -import * as string from "../test-data/string" +import * as number from "../data/number" +import * as O from "../data/Option" +import * as P from "../data/Predicate" +import * as RA from "../data/ReadonlyArray" +import * as string from "../data/string" import * as U from "../util" describe("SemiProduct", () => { diff --git a/test/typeclass/Semigroup.ts b/test/typeclass/Semigroup.ts index 57207427d..afd9cb9c5 100644 --- a/test/typeclass/Semigroup.ts +++ b/test/typeclass/Semigroup.ts @@ -1,8 +1,8 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as order from "@fp-ts/core/typeclass/Order" import * as _ from "@fp-ts/core/typeclass/Semigroup" -import * as number from "../test-data/number" -import * as string from "../test-data/string" +import * as number from "../data/number" +import * as string from "../data/string" import * as U from "../util" describe("Semigroup", () => { diff --git a/test/typeclass/Traversable.ts b/test/typeclass/Traversable.ts index 550f50dfa..2a78856f0 100644 --- a/test/typeclass/Traversable.ts +++ b/test/typeclass/Traversable.ts @@ -1,7 +1,7 @@ import { pipe } from "@fp-ts/core/internal/Function" import * as _ from "@fp-ts/core/typeclass/Traversable" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" +import * as O from "../data/Option" +import * as RA from "../data/ReadonlyArray" import * as U from "../util" describe("Traversable", () => { diff --git a/test/typeclass/TraversableFilterable.ts b/test/typeclass/TraversableFilterable.ts deleted file mode 100644 index 92df4d510..000000000 --- a/test/typeclass/TraversableFilterable.ts +++ /dev/null @@ -1,36 +0,0 @@ -import * as _ from "@fp-ts/core/typeclass/TraversableFilterable" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" -import * as U from "../util" - -describe("TraversableFilterable", () => { - it("traverseFilter", () => { - const traverseFilter = _.traverseFilter( - RA.TraversableFilterable - )(O.Applicative) - const f = traverseFilter((s: string) => - s.length > 2 ? O.some(false) : s.length > 1 ? O.some(true) : O.none - ) - U.deepStrictEqual(f([]), O.some([])) - U.deepStrictEqual(f(["a"]), O.none) - U.deepStrictEqual(f(["a", "aa"]), O.none) - U.deepStrictEqual(f(["aa"]), O.some(["aa"])) - U.deepStrictEqual(f(["aaa"]), O.some([])) - U.deepStrictEqual(f(["aaa", "aa"]), O.some(["aa"])) - }) - - it("traversePartition", () => { - const traversePartition = _.traversePartition( - RA.TraversableFilterable - )(O.Applicative) - const f = traversePartition((s: string) => - s.length > 2 ? O.some(false) : s.length > 1 ? O.some(true) : O.none - ) - U.deepStrictEqual(f([]), O.some([[], []] as const)) - U.deepStrictEqual(f(["a"]), O.none) - U.deepStrictEqual(f(["a", "aa"]), O.none) - U.deepStrictEqual(f(["aa"]), O.some([[], ["aa"]] as const)) - U.deepStrictEqual(f(["aaa"]), O.some([["aaa"], []] as const)) - U.deepStrictEqual(f(["aaa", "aa"]), O.some([["aaa"], ["aa"]] as const)) - }) -}) diff --git a/test/typeclass/TraversableWithIndex.ts b/test/typeclass/TraversableWithIndex.ts index 57520493f..5a0cbbf1b 100644 --- a/test/typeclass/TraversableWithIndex.ts +++ b/test/typeclass/TraversableWithIndex.ts @@ -1,7 +1,7 @@ import { pipe } from "@fp-ts/core/internal/Function" +import * as O from "../data/Option" +import * as RA from "../data/ReadonlyArray" import * as _ from "../limbo/TraversableWithIndex" -import * as O from "../test-data/Option" -import * as RA from "../test-data/ReadonlyArray" import * as U from "../util" describe("TraversableWithIndex", () => { diff --git a/vitest.config.ts b/vitest.config.ts index 8afef943f..9469eb3d4 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -7,7 +7,7 @@ export default defineConfig({ include: ["./test/**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], exclude: [ "./test/util.ts", - "./test/test-data/*.ts", + "./test/data/*.ts", "./test/limbo/*.ts" ], globals: true From a14a0a2eb2630283252fd58e3a8110342fba3061 Mon Sep 17 00:00:00 2001 From: gcanti Date: Mon, 28 Nov 2022 14:22:09 +0100 Subject: [PATCH 2/3] annotate src/internal/Function with internal tag --- src/internal/Function.ts | 44 ++++++++++++++++++++-------------------- test/data/Option.ts | 5 ++++- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/internal/Function.ts b/src/internal/Function.ts index f0e49ae96..2b02a2d18 100644 --- a/src/internal/Function.ts +++ b/src/internal/Function.ts @@ -1,27 +1,17 @@ -/** - * @since 1.0.0 - */ +/** @internal */ -/** - * A lazy argument. - * - * @since 1.0.0 - */ -export interface LazyArg { - (): A -} -/** - * @since 1.0.0 - */ +/** @internal */ export const identity = (a: A): A => a -/** - * @since 1.0.0 - */ +/** @internal */ export function pipe(a: A): A +/** @internal */ export function pipe(a: A, ab: (a: A) => B): B +/** @internal */ export function pipe(a: A, ab: (a: A) => B, bc: (b: B) => C): C +/** @internal */ export function pipe(a: A, ab: (a: A) => B, bc: (b: B) => C, cd: (c: C) => D): D +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -29,6 +19,7 @@ export function pipe( cd: (c: C) => D, de: (d: D) => E ): E +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -37,6 +28,7 @@ export function pipe( de: (d: D) => E, ef: (e: E) => F ): F +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -46,6 +38,7 @@ export function pipe( ef: (e: E) => F, fg: (f: F) => G ): G +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -56,6 +49,7 @@ export function pipe( fg: (f: F) => G, gh: (g: G) => H ): H +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -67,6 +61,7 @@ export function pipe( gh: (g: G) => H, hi: (h: H) => I ): I +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -79,6 +74,7 @@ export function pipe( hi: (h: H) => I, ij: (i: I) => J ): J +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -92,6 +88,7 @@ export function pipe( ij: (i: I) => J, jk: (j: J) => K ): K +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -106,6 +103,7 @@ export function pipe( jk: (j: J) => K, kl: (k: K) => L ): L +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -121,6 +119,7 @@ export function pipe( kl: (k: K) => L, lm: (l: L) => M ): M +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -137,6 +136,7 @@ export function pipe( lm: (l: L) => M, mn: (m: M) => N ): N +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -154,7 +154,7 @@ export function pipe( mn: (m: M) => N, no: (n: N) => O ): O - +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -173,7 +173,7 @@ export function pipe( no: (n: N) => O, op: (o: O) => P ): P - +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -193,7 +193,7 @@ export function pipe( op: (o: O) => P, pq: (p: P) => Q ): Q - +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -214,7 +214,7 @@ export function pipe( pq: (p: P) => Q, qr: (q: Q) => R ): R - +/** @internal */ export function pipe( a: A, ab: (a: A) => B, @@ -236,7 +236,7 @@ export function pipe( qr: (q: Q) => R, rs: (r: R) => S ): S - +/** @internal */ export function pipe( a: A, ab: (a: A) => B, diff --git a/test/data/Option.ts b/test/data/Option.ts index 37b952948..c3890a22f 100644 --- a/test/data/Option.ts +++ b/test/data/Option.ts @@ -13,7 +13,6 @@ * @since 1.0.0 */ import type { Kind, TypeLambda } from "@fp-ts/core/HKT" -import type { LazyArg } from "@fp-ts/core/internal/Function" import { identity, pipe } from "@fp-ts/core/internal/Function" import type * as extendable from "@fp-ts/core/test/limbo/Extendable" import type * as alternative from "@fp-ts/core/typeclass/Alternative" @@ -39,6 +38,10 @@ import type * as foldableWithIndex from "../limbo/FoldableWithIndex" import * as nonEmptyArray from "./NonEmptyArray" import * as nonEmptyReadonlyArray from "./NonEmptyReadonlyArray" +export interface LazyArg { + (): A +} + export interface None { readonly _tag: "None" } From ca14942cf8a9aece1c8317833c89cda494cc1c5b Mon Sep 17 00:00:00 2001 From: gcanti Date: Mon, 28 Nov 2022 14:25:21 +0100 Subject: [PATCH 3/3] chore --- src/typeclass/SemiProduct.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/typeclass/SemiProduct.ts b/src/typeclass/SemiProduct.ts index 112db620a..c8b6958dd 100644 --- a/src/typeclass/SemiProduct.ts +++ b/src/typeclass/SemiProduct.ts @@ -100,7 +100,7 @@ export const productMany = ( export const andThenBind = (F: SemiProduct) => ( name: Exclude, - fb: Kind + that: Kind ) => ( self: Kind @@ -113,7 +113,7 @@ export const andThenBind = (F: SemiProduct) => > => pipe( self, - F.product(fb), + F.product(that), F.imap( ([a, b]) => Object.assign({}, a, { [name]: b }) as any, ({ [name]: b, ...rest }) => [rest, b] as any