-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
804a890
commit 9fb3ac4
Showing
32 changed files
with
14,004 additions
and
2,709 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Dependencies | ||
/node_modules | ||
|
||
# Production | ||
/build | ||
|
||
# Generated files | ||
.docusaurus | ||
.cache-loader | ||
|
||
# Misc | ||
.DS_Store | ||
.env.local | ||
.env.development.local | ||
.env.test.local | ||
.env.production.local | ||
|
||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Website | ||
|
||
This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
presets: [require.resolve('@docusaurus/core/lib/babel/preset')], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
--- | ||
|
||
# Concepts |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
--- | ||
|
||
# Getting started |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
--- | ||
tags: | ||
- array | ||
--- | ||
|
||
# Filter | ||
|
||
`filter<X>(p: (x: X) => unknown)` focus on the subarray of values satisfying the predicate. | ||
|
||
```typescript | ||
const focus = flow( | ||
eq<number[]>(), | ||
filter((x) => x % 2 === 0), | ||
) | ||
const res: number[] | undefined = focus.view([5, 4, 3, 2]) // [4, 2] | ||
const modified = focus.update((xs) => xs.toSorted(), [5, 4, 3, 2]) // [5, 2, 3, 4] | ||
``` | ||
|
||
When reading, if predicate is a type guard, type of the returned value will be accordingly restricted. | ||
|
||
```typescript | ||
const focus = flow( | ||
eq<(number | string)[]>(), | ||
filter((x) => typeof x === 'number'), | ||
) | ||
const res: number[] = focus.view([2, 'a']) // res === [2] | ||
``` | ||
|
||
While writing, if the provided array is shorter, last elements are deleted. | ||
|
||
```typescript | ||
const focus = flow( | ||
eq<number[]>(), | ||
filter((x) => x % 2 === 0), | ||
) | ||
const res: number[] | undefined = focus.view([0, 1, 2, 3]) // [4, 2] | ||
const modified = focus.put([8], (xs) => xs.toSorted()) // [5, 2, 3, 4] | ||
``` | ||
|
||
While writing, if the provided array is longer, extra elements are appended. | ||
|
||
While writing to a non-existing focus, will append the value. | ||
|
||
```typescript | ||
const focus = flow( | ||
eq<number[]>(), | ||
filter((x) => x > 3), | ||
) | ||
const updated = focus.put(5, [0, 3]) // updated === [0, 3, 5] | ||
``` | ||
|
||
## Unlawful behavior | ||
|
||
[**get after put**](/docs/optics/#laws-of-lenses) will not hold when writing a value which do not satisfy the predicate. | ||
|
||
```typescript | ||
const updated = focus.put(0, [2, 4, 6]) // updated === [2, 0, 6] | ||
const res = focus.view(updated) // res === 6 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
--- | ||
|
||
# Lens |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
--- | ||
--- | ||
|
||
# Nth | ||
|
||
`nth(index: number)` focus on the nth element of a tuple. When working with an array, use [`at`](../removables/at) instead. | ||
|
||
```typescript | ||
type Source = [number, string, boolean] | ||
const source: Source = [1, 'a', true] | ||
const focus = flow(eq<Source>(), nth(1)) | ||
const res: string = focus.view(source) // res === 'a' | ||
const updated = focus.put('A', source) // updated === [1, 'A', true] | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
--- | ||
tags: | ||
- array | ||
--- | ||
|
||
# At | ||
|
||
`at(index: number)` focus on the nth element of an array. If `index` is negative, indexes backward starting from last position of the array. When working with a tuple, use [`nth`](../lens/nth) instead. | ||
|
||
```typescript | ||
const focus = flow(eq<string[]>(), at(-1)) | ||
const res: string | undefined = focus.view(['a', 'b']) // res === 'b' | ||
const updated = focus.put('B', ['a', 'B']) // updated === ['A', 'b'] | ||
const removed = focus.exec(REMOVE, ['a', 'b']) // removed === ['a'] | ||
``` |
44 changes: 44 additions & 0 deletions
44
packages/docs/website/docs/03-optics/01-removables/find.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
--- | ||
tags: | ||
- array | ||
- unlawful | ||
--- | ||
|
||
# Find | ||
|
||
`find<X>(p: (x: X) => unknown)` focus on the first value of an array which satisfies a predicate. | ||
|
||
```typescript | ||
const focus = flow( | ||
eq<number[]>(), | ||
find((x) => x > 3), | ||
) | ||
const res: number | undefined = focus.view([2, 4, 6]) // res === 4 | ||
const updated = focus.put(5, [2, 4, 6]) // updated === [2, 5, 6] | ||
const removed = focus.exec(REMOVE, [2, 4, 6]) // removed === [2, 6] | ||
``` | ||
|
||
When reading, if predicate is a type guard, type of the returned value will be accordingly restricted. | ||
|
||
```typescript | ||
const focus = flow( | ||
eq<number | string[]>(), | ||
find((x) => typeof x === 'number'), | ||
) | ||
const res: number | undefined = focus.view([2, 'a']) // res === 2 | ||
``` | ||
|
||
When writing to a non-existing focus, will append the value. | ||
|
||
```typescript | ||
const updated = focus.put(5, [0, 3]) // updated === [0, 3, 5] | ||
``` | ||
|
||
## Unlawful behavior | ||
|
||
[**get after put**](/docs/optics/#laws-of-lenses) will not hold when writing a value which do not satisfy the predicate. | ||
|
||
```typescript | ||
const updated = focus.put(0, [2, 4, 6]) // updated === [2, 0, 6] | ||
const res = focus.view(updated) // res === 6 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
--- | ||
|
||
# Removables | ||
|
||
Removables are optials that can remove the focus. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
--- | ||
--- | ||
|
||
# Optics | ||
|
||
## Intro | ||
|
||
You can think of a **lens** as a way to focus on a part of an object. It lets you read or modify its value by returning an updated copy. | ||
|
||
```typescript | ||
exemple | ||
``` | ||
|
||
**Optics** is the broader category which lens belongs to. An **optional** is an optitcs who's focus is not garanteed to exist. A **traversal** can have more than one focus. Some optics lets you remove the focus, some can convert between types or units of mesurement. Most importantly, they compose with each other. | ||
|
||
``` | ||
exemple | ||
``` | ||
|
||
## Getting started | ||
|
||
```typescript | ||
type T = { a: string } | ||
Eq<T>() | ||
at('a')(Eq<T>()) | ||
flow(Eq<T>(), at('a')) | ||
``` | ||
## Use cases | ||
- structural coupling (shape) | ||
- hidden dependancy | ||
- state-gui | ||
- API | ||
## Laws of Lenses | ||
The behaviors we expect of a lens can be expressed by the following axioms: | ||
- **get after set**: `l.get(l.set(a)(s)) === a` | ||
- **set after get**: `l.set(l.get(s))(s) === s` | ||
- **set after set**: `l.set(b)(l.set(a)(s)) === l.set(b)(s)` | ||
In particular, "set after set" implies idempotency. | ||
- **idempotency**: `l.set(a)(l.set(a)(s)) === l.set(a)(s)` | ||
In plain English: | ||
- **get after set**: If we set a value and then read the focus, we should get the same value. | ||
- **set after get**: If we get a value, and then set the focus to that value, we should get an identical object. | ||
- **set after set**: If we set a value twice (with different values), it should be the same as only setting the second value. | ||
Other types of optics obey similar axioms. | ||
Sometimes it pays to break the laws. Some [useful lenses](/docs/tags/unlawful) do not respect all of the axioms, and it will be documented. | ||
## Roadmap | ||
- traversals | ||
## Out of scope | ||
- polymorphic optics | ||
## Prior art | ||
- [calmm-js/partial.lenses](https://github.com/calmm-js/partial.lenses) presents a wide collection of optics from the JavaScript era. | ||
- [optics-ts](https://akheron.github.io/optics-ts/) is a very well made TypeScript library. It is my main inspiration for this project. Beside differences in ergonomics, I wanted something that was way less demanding on the TypeScript compiler. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
--- | ||
--- | ||
|
||
# Finite State Machines | ||
|
||
## Use cases | ||
|
||
- replace multiple flags that do not freely combine | ||
- express a succession idea | ||
- regroup the logic that was dispersed in handlers at one place | ||
- think state then event | ||
|
||
## Roadmap | ||
|
||
- child states | ||
- parallel states | ||
|
||
## Prior art | ||
|
||
- [XState](https://stately.ai/docs/xstate) is the most popular implementation of finite state machines in TypeScript. One core idea in XState is to have the machine trigger effects on state change. We are aiming for just the opposite, letting an outside observer (such as react `useEfect`) react to state changes. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
--- | ||
|
||
# Atoms |
Oops, something went wrong.