Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

version 0.1.0 #46

Merged
merged 80 commits into from
Jan 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
15a1a4a
add missing readonly modifiers
gcanti Jan 15, 2023
3d5aebd
add Function module
gcanti Jan 15, 2023
ef066c6
add Ordering module
gcanti Jan 15, 2023
f418131
add Predicate module
gcanti Jan 15, 2023
aed9c17
add Boolean module
gcanti Jan 15, 2023
723bb40
add Number module
gcanti Jan 15, 2023
864a4c3
add String module
gcanti Jan 15, 2023
c4ed639
add Identity module
gcanti Jan 15, 2023
c80e350
add Equivalence module
gcanti Jan 16, 2023
2caf47a
add Option module
gcanti Jan 16, 2023
781d23c
add Either module
gcanti Jan 16, 2023
4e73d66
add These module
gcanti Jan 16, 2023
9cbf072
add CovariantWithIndex, FilterableWithIndex, TraversableFilterable mo…
gcanti Jan 16, 2023
ee777eb
add ReadonlyArray module
gcanti Jan 16, 2023
8a579bb
chore: remove @category mutations
gcanti Jan 16, 2023
1d9fbe4
chore: remove @fp-ts/data
gcanti Jan 16, 2023
e21d82f
ReadonlyArray: add CovariantWithIndex, FilterableWithIndex instances
gcanti Jan 16, 2023
0db018e
chore: remove /test/data
gcanti Jan 16, 2023
d788966
FilterableWithIndex: 100% coverage
gcanti Jan 16, 2023
de4f635
remove NonEmptyTraversable typeclass
gcanti Jan 16, 2023
8165742
docs: add Equivalence to Overview.md
gcanti Jan 16, 2023
76dd577
update README
gcanti Jan 16, 2023
36c80fc
add the prefix @fp-ts/core to the _tag of the data types
gcanti Jan 16, 2023
df3cb49
chore
gcanti Jan 16, 2023
44d7491
Boolean: add not combinator
gcanti Jan 16, 2023
0b3b3df
Chainable: remove readonly from bind return type
gcanti Jan 17, 2023
b4a991d
Compactable: remove readonly from separate
gcanti Jan 17, 2023
a1826ae
Filterable: remove readonly from partitionMap
gcanti Jan 17, 2023
2e704c5
Filterable: remove readonly from partition
gcanti Jan 17, 2023
debc39d
TraversableFilterable: remove readonly from traversePartitionMap, tra…
gcanti Jan 17, 2023
5892aae
Covariant: remove readonly from let
gcanti Jan 17, 2023
6b07599
bindTo: remove readonly
gcanti Jan 17, 2023
bd1fbcb
tupled: remove readonly
gcanti Jan 17, 2023
1f41108
Product, SemiProduct: remove readonly from typeclass members
gcanti Jan 17, 2023
2676b88
andThenBind: remove readonly
gcanti Jan 17, 2023
08120d4
productFlatten: remove readonly
gcanti Jan 17, 2023
f0db9b2
nonEmptyStruct: remove readonly
gcanti Jan 17, 2023
48295e9
struct: remove readonly
gcanti Jan 17, 2023
d0d5dc4
struct: remove readonly
gcanti Jan 17, 2023
82a0032
nonEmptyTuple: remove readonly
gcanti Jan 17, 2023
17b5447
Semigroup, Monoid: tuple: remove readonly
gcanti Jan 17, 2023
7b5de2a
ReadonlyArray: remove useless instance
gcanti Jan 17, 2023
5849b60
ReadonlyArray: remove readonly from imap, let, flap, as, flatten, bin…
gcanti Jan 17, 2023
bd12b4c
rename `productFlatten` to `element`
gcanti Jan 18, 2023
c1f1c5d
Order: add array combinator
gcanti Jan 19, 2023
79bb968
Semigroup: add array, readonlyArray combinator
gcanti Jan 19, 2023
fb293fc
Monoid: add array, readonlyArray combinators
gcanti Jan 19, 2023
e04d2d6
data.md: add struct section
gcanti Jan 19, 2023
804e727
data.md: add string section
gcanti Jan 19, 2023
b0d2d11
data.md: add numbers section
gcanti Jan 19, 2023
d6dc0e1
data.md: add booleans section
gcanti Jan 19, 2023
9ee83b0
Order: add bigint instance
gcanti Jan 19, 2023
5eca4d0
add ReadonlyRecord module
gcanti Jan 19, 2023
f2ffe2a
revert _tag changes
gcanti Jan 20, 2023
50bec74
add Bigint module
gcanti Jan 20, 2023
6ced8da
add Symbol module
gcanti Jan 20, 2023
d5e30f5
add Struct module
gcanti Jan 20, 2023
92d4c5d
add modules from @fp-ts/data
gcanti Jan 20, 2023
89e2868
Order: make compare binary
gcanti Jan 20, 2023
ae7ec25
Semigroup: make combine binary
gcanti Jan 20, 2023
016764f
Semigroup: make combineMany binary
gcanti Jan 20, 2023
64ff8de
SemiProduct: make product binary
gcanti Jan 20, 2023
75ee446
SemiProduct: make productMany binary
gcanti Jan 20, 2023
292848f
SemiCoproduct: make coproduct binary
gcanti Jan 20, 2023
1a4b5eb
SemiCoproduct: make coproductMany binary
gcanti Jan 20, 2023
94edf17
add Tuple module
gcanti Jan 20, 2023
5798334
more docs
gcanti Jan 21, 2023
c1f7bd9
Order: add struct
gcanti Jan 21, 2023
0ff528f
Number: add SemigroupMin, SemigroupMax, MonoidMin, MonoidMax
gcanti Jan 21, 2023
d1e84ab
Boolean: add all, any
gcanti Jan 21, 2023
80daf05
Add tracing code for Option
mikearnaldi Jan 21, 2023
cff0047
fix dtslint
gcanti Jan 21, 2023
45c4507
Spread structural-tracking across all data types
gcanti Jan 21, 2023
b497f28
Bigint: add divide
gcanti Jan 21, 2023
9c84d79
chore
gcanti Jan 23, 2023
02ea72a
Predicate: optimise getSemigroupAny, getSemigroupAll
gcanti Jan 23, 2023
eaf2856
rename size to length
gcanti Jan 23, 2023
ef2cbc4
String: rename trimLeft, trimRight
gcanti Jan 23, 2023
3c74656
downgrade docs-ts
gcanti Jan 23, 2023
3e87daf
update docs
gcanti Jan 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/modern-tomatoes-promise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": minor
---

add modules from @fp-ts/data
5 changes: 5 additions & 0 deletions .changeset/red-moons-hope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fp-ts/core": patch
---

Add tracking code for Option
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,55 @@
# @fp-ts/core

## next

**Breaking changes**

- remove `NonEmptyTraversable` module
- `Semigroup`
- make `combine` binary
- make `combineMany` binary
- `SemiCoproduct`
- make `coproduct` binary
- make `coproductMany` binary
- `SemiProduct`
- make `product` binary
- make `productMany` binary
- rename `productFlatten` to `element`
- `Order`
- make `compare` binary

**New Features**

- `Boolean`
- add `not` combinator
- `Order`
- add `array` combinator
- add `bigint` instance
- `Monoid`
- add `array`, `readonlyArray` combinators
- `Semigroup`
- add `array`, `readonlyArray` combinators
- new modules
- `typeclass/Equivalence`
- `typeclass/Filterable`
- `typeclass/TraversableFilterable`
- `Bigint`
- `Boolean`
- `Either`
- `Function`
- `Identity`
- `Number`
- `Option`
- `Ordering`
- `Predicate`
- `ReadonlyArray`
- `ReadonyRecord`
- `String`
- `Struct`
- `Symbol`
- `These`
- `Tuple`

## 0.0.11

### Patch Changes
Expand Down
141 changes: 141 additions & 0 deletions Either.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# The `Either` data type

The `Either` data type is a powerful and flexible tool for handling potentially failed computations in functional programming. It can be found in the `@fp-ts/core/Either` module, and it has two variants, `Left` and `Right`, which can be used to represent different outcomes.

The `Left` variant is used to represent a failure, and it can contain useful information such as an error message or a failure code. The `Right` variant, on the other hand, is used to represent a successful outcome, and it can contain the result of the computation.

Unlike the `Option` type, `Either` allows you to attach additional information to the failure case, making it more informative.
In this usage, `None` is replaced with a `Left` which can contain useful information. `Right` takes the place of `Some`.

# Definition

The `Either` data type is the union of two members: `Left` and `Right`. The way chosen by the `@fp-ts/core` library to model this union in TypeScript is to use a feature of the language called [Discriminating Unions](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions):

> A common technique for working with unions is to have a single field which uses literal types which you can use to let TypeScript narrow down the possible current type

Here's the complete definition of the `Either` type:

```ts
export type Left<E> = {
readonly _tag: "Left";
readonly left: E;
};

export type Right<A> = {
readonly _tag: "Right";
readonly right: A;
};

export type Either<E, A> = Left<E> | Right<A>;
```

# Using `Either`

To create an instance of `Either`, you can use the `right` and `left` constructors, which construct a new `Either` holding a `Right` or `Left` value respectively.

```ts
import { left, right } from "@fp-ts/core/Either";

const success: Either<string, number> = right(1);
const failure: Either<string, number> = left("error message");
```

You can also use the `fromOption` function to convert an `Option` to an `Either`.

```ts
import { pipe } from "@fp-ts/core/Function";
import { fromOption } from "@fp-ts/core/Either";
import { none, some } from "@fp-ts/core/Option";

const success: Either<string, number> = pipe(
some(1),
fromOption("error message")
);
const failure: Either<string, number> = pipe(
none(),
fromOption("error message")
);
```

The `fromOption` function requires an argument because it needs to know what value to use for the `Left` variant of the `Either` type when given a `None`. In the example, the argument "error message" is used as the value for the `Left` variant when `None` is encountered. This allows `Either` to provide more information about why a failure occurred.

# Working with `Either`

Once you have an instance of `Either`, you can use the various functions provided in the `@fp-ts/core/Either` module to work with it.

The `map` and `mapLeft` functions can be used to transform the `Right` and `Left` values respectively.

```ts
import { pipe } from "@fp-ts/core/Function";
import { left, right, map, mapLeft } from "@fp-ts/core/Either";

const success: Either<string, number> = pipe(
right(1),
map((x) => x + 1)
); // right(2)

const failure: Either<string, number> = pipe(
left("error message"),
mapLeft((x) => x + "!")
); // left("error message!")
```

# Handling failing computations

Let's see how to use the `Either` data type to model a computation that can fail, such as a function that can throw an exception based on certain conditions. Let's take the case of the following function:

```ts
function parseNumber(s: string): number {
const n = parseFloat(s);
if (isNaN(n)) {
throw new Error(`Cannot parse '${s}' as a number`);
}
return n;
}
```

An alternative to throwing an exception is to always return a value, but this value will be of type `Either<string, number>` instead of `number`, with the following interpretation:

- if `parseNumber` returns a `Left<string>` value, it means that the computation failed, and the `Left` contains an error message or other information about the failure
- if the result is instead a `Right<number>` value, it means that the computation succeeded and the computed value is wrapped inside the `Right`

Let's see how we can rewrite the `parseNumber` function without throwing exceptions and using the `Either` data type instead:

```ts
import { Either, left, right } from "@fp-ts/core/Either";

function parseNumber(s: string): Either<string, number> {
const n = parseFloat(s);
return isNaN(n) ? left(`Cannot parse '${s}' as a number`) : right(n);
}

console.log(parseNumber("2")); // right(2)
console.log(parseNumber("Not a number")); // left("Cannot parse 'Not a number' as a number")
```

# Pattern matching

The `match` function allows us to match on the `Left` and `Right` cases of an `Either` value and provide different actions for each.

We can use the `match` function to handle the `Either` value returned by `parseNumber` and decide what to do based on whether it's a `Left` or a `Right`.

```ts
import { pipe } from "@fp-ts/core/Function";
import { match } from "@fp-ts/core/Either";

// parseNumber returns an Either<string, number>
const result = parseNumber("Not a number");

// Using pipe and match to pattern match on the result
const output = pipe(
result,
match(
// If the result is a Left, return an error string
(error) => `Error: ${error}`,
// If the result is a Right, return a string with the number
(n) => `The number is ${n}`
)
);

console.log(output); // Output: Error: Cannot parse 'Not a number' as a number
```
120 changes: 120 additions & 0 deletions Option.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# The `Option` data type

The `Option` data type is a powerful and flexible tool for handling potentially failed computations in functional programming. It can be found in the `@fp-ts/core/Option` module, and it has two variants, `None` and `Some`, which can be used to represent different outcomes.

There are two possible interpretations of the `Option` data type:

1. as a representation of the result of a computation that can fail or return a value of type `A`
2. as a representation of an optional value of type `A`

In the first of these two interpretations, the `None` union member represents the result of a computation that has failed and therefore was not able to return any value, while the `Some<A>` union member represents the result of a computation that has succeeded and was able to return a value of type `A`.

In the second of these two interpretations, the `None` union member represents the absence of the value, while the `Some<A>` union member represents the presence of the value of type `A`

# Definition

The `Option` data type is the union of two members: `None` and `Some`. The way chosen by the `@fp-ts/core` library to model this union in TypeScript is to use a feature of the language called [Discriminating Unions](https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unions):

> A common technique for working with unions is to have a single field which uses literal types which you can use to let TypeScript narrow down the possible current type

Here's the complete definition of the `Option` type:

```ts
export type None = {
readonly _tag: "None";
};

export type Some<A> = {
readonly _tag: "Some";
readonly value: A;
};

export type Option<A> = None | Some<A>;
```

# Using `Option`

To create an instance of `Option`, you can use the `some` and `none` constructors, which construct a new `Option` holding a `Some` or `None` value respectively.

```ts
import { none, some } from "@fp-ts/core/Either";

const success: Option<number> = some(1);
const failure: Option<number> = none();
```

# Working with `Option`

Once you have an instance of `Option`, you can use the various functions provided in the `@fp-ts/core/Option` module to work with it.

The `map` function can be used to transform the `Some` values.

```ts
import { pipe } from "@fp-ts/core/Function";
import { some, map } from "@fp-ts/core/Option";

const success: Option<number> = pipe(
some(1),
map((x) => x + 1)
); // some(2)
```

# Handling failing computations

Let's see how to use the `Option` data type to model a computation that can fail, such as a function that can throw an exception based on certain conditions. Let's take the case of the following function:

```ts
function parseNumber(s: string): number {
const n = parseFloat(s);
if (isNaN(n)) {
throw new Error();
}
return n;
}
```

An alternative to throwing an exception is to always return a value, but this value will be of type `Option<number>` instead of `number`, with the following interpretation:

- if `parseNumber` returns a `None` value, it means that the computation failed
- if the result is instead a `Some<number>` value, it means that the computation succeeded and the computed value is wrapped inside the `Some`

Let's see how we can rewrite the `parseNumber` function without throwing exceptions and using the `Option` data type instead:

```ts
import { Option, none, some } from "@fp-ts/core/Option";

function parseNumber(s: string): Option<number> {
const n = parseFloat(s);
return isNaN(n) ? none() : some(n);
}

console.log(parseNumber("2")); // some(2)
console.log(parseNumber("Not a number")); // none()
```

# Pattern matching

The `match` function allows us to match on the `None` and `Some` cases of an `Option` value and provide different actions for each.

We can use the `match` function to handle the `Option` value returned by `parseNumber` and decide what to do based on whether it's a `None` or a `Some`.

```ts
import { pipe } from "@fp-ts/core/Function";
import { match } from "@fp-ts/core/Option";

// parseNumber returns an Option<number>
const result = parseNumber("Not a number");

// Using pipe and match to pattern match on the result
const output = pipe(
result,
match(
// If the result is a None, return an error string
() => `Error: ${error}`,
// If the result is a Some, return a string with the number
(n) => `The number is ${n}`
)
);

console.log(output); // Output: Error: Cannot parse 'Not a number' as a number
```
28 changes: 15 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,40 @@ Functional programming in TypeScript

# Typed functional programming in TypeScript

This project represents the next major iteration of [`fp-ts`](https://github.com/gcanti/fp-ts) and it's objective is a reconciliation with [`Effect`](https://github.com/Effect-TS) in order to unify the ecosystems.
This project represents the next major iteration of [`fp-ts`](https://github.com/gcanti/fp-ts) and it's objective is a reconciliation with [`@effect`](https://github.com/Effect-TS) in order to unify the ecosystems.

The [`Effect`](https://github.com/Effect-TS) project will reduce it's scope to simply being an effect system and will delegate to `fp-ts org` all the lower level abstractions such as typeclasses and common data structures.
The [`@effect`](https://github.com/Effect-TS) project will reduce it's scope to simply being an effect system and will delegate to `fp-ts org` all the lower level abstractions such as typeclasses and common data structures.

The objective of the `fp-ts org` in github and in npm (`@fp-ts`) is to simplify structure and management of the project, have smaller and better scoped packages.

Our "current" idea (that is well open for changes) is for `fp-ts org` to have:

- `@fp-ts/core` with the new `HKT` implementation and the most common typeclasses such as `Monad`
- `@fp-ts/data` with `Option`, `Either`, `ReadonlyArray`, `List` and the most common data structures together with data related typeclasses (i.e. `Compactable`, etc)
- `@fp-ts/optics` with an optic implementation that will provide also optics for structures in `@fp-ts/data`
- `@fp-ts/schema` with a concrete codec such as `io-ts` again for all the structures in `@fp-ts/data`
- The [`@fp-ts/core`](https://github.com/fp-ts/core) library features a new implementation of the Higher Kinded Type (HKT) pattern, including common typeclasses such as `Monad` and widely-used data types like `Option`, `Either`, and `ReadonlyArray`
- [`@fp-ts/schema`](https://github.com/fp-ts/schema) offers schema validation with static type inference, including decoders for data structures in `@fp-ts/core` and `@effect/data`
- [`@fp-ts/optic`](https://github.com/fp-ts/optic) provides optics for structures in both `@fp-ts/core` and `@effect/data`

And for [`Effect`](https://github.com/Effect-TS) to have:
For those using [`fp-ts`](https://github.com/gcanti/fp-ts) v2 and its ecosystem, roughly these are the equivalents:

- `@effect/core` with the effect system
- `@effect/query` with the query impl
- `@effect/*` every other effect based impl
- [`fp-ts`](https://github.com/gcanti/fp-ts) -> [`@fp-ts/core`](https://github.com/fp-ts/core) + [`@effect/*` packages](https://github.com/Effect-TS)
- [`io-ts`](https://github.com/gcanti/io-ts) -> [`@fp-ts/schema`](https://github.com/fp-ts/schema)
- [`monocle-ts`](https://github.com/gcanti/monocle-ts) -> [`@fp-ts/optic`](https://github.com/fp-ts/optic)

Note that [`Effect`](https://github.com/Effect-TS) will not have base structures like `Option` / `Either` / `List` and typeclasses like `Monad` / `Functor` and [`fp-ts`](https://github.com/fp-ts) will not have effect execution modules like `Task` / `IO` as both projects are made to be the same ecosystem and each answer a specific set of needs in the best way possible.
Note that `@fp-ts/core` will not contain any effect system (e.g. `Task`, `TaskEither`, `ReaderTaskEither`) since the handling of effects is entirely delegated to the packages contained in [`@effect/*`](https://github.com/Effect-TS).

# Installation

To install the **pre-alpha** version:
To install the **alpha** version:

```
npm install @fp-ts/core
```

# Documentation

- [Overview](./Overview.md)
- [Typeclass overview](./typeclass.md)
- [Data overview](./data.md)
- [The `Option` data type](./Option.md)
- [The `Either` data type](./Either.md)
- [API Reference](https://fp-ts.github.io/core/)

# License
Expand Down
Loading