From d66a27e742c519aaa67dee0338a0b78517a6578d Mon Sep 17 00:00:00 2001 From: Caleb Stimpson Date: Sat, 7 Sep 2024 14:24:24 -0600 Subject: [PATCH 1/3] docs: add docs page "Functional programming and Jotai" --- .../functional-programming-and-jotai.mdx | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 docs/basics/functional-programming-and-jotai.mdx diff --git a/docs/basics/functional-programming-and-jotai.mdx b/docs/basics/functional-programming-and-jotai.mdx new file mode 100644 index 0000000000..1078821470 --- /dev/null +++ b/docs/basics/functional-programming-and-jotai.mdx @@ -0,0 +1,67 @@ +--- +title: Functional programming and Jotai +nav: 6.04 +--- + +### Unexpected similarities + +If you look at getter functions long enough, you may see a striking resemblence +to a certain JavaScript language feature. + +```tsx +const nameAtom = atom('Visitor') +const countAtom = atom(1) +const greetingAtom = atom((get) => { + const name = get(nameAtom) + const count = get(countAtom) + return ( +
+ Hello, {nameAtom}! You have visited this page {countAtom} times. +
+ ) +}) +``` + +Now, compare that code with `async`–`await`: +```tsx +const namePromise = Promise.resolve('Visitor') +const countPromise = Promise.resolve(1) +const greetingPromise = (async function() { + const name = await namePromise; + const count = await countPromise; + return ( +
+ Hello, {nameAtom}! You have visited this page {countAtom} times. +
+ ) +})() +``` + +This similarity is no coincidence. Both atoms and promises are **Monads**, a +concept from **functional programming**. The syntax used in both examples is +called **do-notation**, a syntax sugar for the plainer monad interface. + +--- + +The monad interface is responsible for the fluidity of the atom and promise +interfaces. The monad interface allowed us to define `greetingAtom` in terms of +`nameAtom` and `countAtom`, and allowed us to define `greetingPromise` in terms +of `namePromise` and `countPromise`. + +For the mathematically inclined, a structure (like `Atom` or `Promise`) is a +monad if you can implement the following functions for it. A fun exercise is +trying to implement `of`, `map` and `join` for Atoms, Promises and Arrays. + +```typescript +type SomeMonad = /* ... */ +declare function of(plainValue: T): SomeMonad +declare function map( + anInstance: SomeMonad, + transformContents: (contents: T) => V +): SomeMonad +declare function join(nestedInstances: SomeMonad>): SomeMonad +``` + +Monads have been an interest to mathematicians for 60 years, and to programmers +for 40. There are countless resources out there on patterns for monads, such +as `Traversable`–`sequence`. Take a look at them! From 0ae24320e2f26e1f93a66c531b311c9fa878c8ae Mon Sep 17 00:00:00 2001 From: Caleb Stimpson Date: Sat, 7 Sep 2024 14:46:49 -0600 Subject: [PATCH 2/3] Briefly mention monads in README --- readme.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/readme.md b/readme.md index 0f5d339add..ed99691126 100644 --- a/readme.md +++ b/readme.md @@ -160,6 +160,13 @@ function Controls() { ... ``` +### Note about functional programming + +Jotai's fluid interface is no accident — atoms are monads, just like promises! +Monads are an [established](https://en.wikipedia.org/wiki/Monad_(functional_programming)) +pattern for modular, pure, robust and understandable code which is [optimized for change](https://overreacted.io/optimized-for-change/). +Read more about [Jotai and monads.](https://jotai.org/docs/basics/functional-programming-and-jotai) + ## Links - [website](https://jotai.org) From 0290bb7fd38649447cf9aa257d5af11f2036d564 Mon Sep 17 00:00:00 2001 From: Caleb Stimpson Date: Sat, 7 Sep 2024 14:51:36 -0600 Subject: [PATCH 3/3] pnpm run prettier --- docs/basics/functional-programming-and-jotai.mdx | 7 ++++--- readme.md | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/basics/functional-programming-and-jotai.mdx b/docs/basics/functional-programming-and-jotai.mdx index 1078821470..f1e08485ef 100644 --- a/docs/basics/functional-programming-and-jotai.mdx +++ b/docs/basics/functional-programming-and-jotai.mdx @@ -23,12 +23,13 @@ const greetingAtom = atom((get) => { ``` Now, compare that code with `async`–`await`: + ```tsx const namePromise = Promise.resolve('Visitor') const countPromise = Promise.resolve(1) -const greetingPromise = (async function() { - const name = await namePromise; - const count = await countPromise; +const greetingPromise = (async function () { + const name = await namePromise + const count = await countPromise return (
Hello, {nameAtom}! You have visited this page {countAtom} times. diff --git a/readme.md b/readme.md index ed99691126..3c4408968b 100644 --- a/readme.md +++ b/readme.md @@ -163,7 +163,7 @@ function Controls() { ### Note about functional programming Jotai's fluid interface is no accident — atoms are monads, just like promises! -Monads are an [established](https://en.wikipedia.org/wiki/Monad_(functional_programming)) +Monads are an [established]() pattern for modular, pure, robust and understandable code which is [optimized for change](https://overreacted.io/optimized-for-change/). Read more about [Jotai and monads.](https://jotai.org/docs/basics/functional-programming-and-jotai)