Password Vegas2024
SSID DevfestSXB
fp-ts
Quand TypeScript devient
fonctionnel
Jordane Grenat
Johan Rouve
Bastien Tran
Agenda
09h00 - Introduction
09h15 - Partie pratique
12h00 - Fin de l'atelier
Programmation fonctionnelle ?
- Fonctions
- Pas d'effets de bord
const square = (n) => n * n;
const numbers = [1, 2, 3, 4, 5];
const result = number.map(square);
// [1, 4, 9, 16, 25]
const allItems = [];
const createToDoItem = (name) => {
const todoItem = {
name: name,
status: 'to do'
};
await db.save(todoItem);
console.log(todoItem);
allItems.push(todoItem);
return todoItem;
}
const createToDoItem = (name) => {
const todoItem = {
name: name,
status: 'to do'
};
await db.save(todoItem);
console.log(todoItem);
return todoItem;
}
const createToDoItem = (name) => {
const todoItem = {
name: name,
status: 'to do'
};
await db.save(todoItem);
return todoItem;
}
const createToDoItem = (name) => {
const todoItem = {
name: name,
status: 'to do'
};
return todoItem;
}
Outils
- fonctions
- map, filter, reduce
- Functor
- Applicative
- Monad
const numbers = [1, 2, 3, -2, 4, 5, 8];
const result = numbers
.filter(isEven)
.map(square);
// [4, 4, 16, 64];
const numbers = [1, 2, 3, -2, 4, 5, 8];
const result = dedupe(numbers
.filter(isEven)
.map(square));
// [4, 16, 64];
const filter = (fn) => (array) => // ...
filter(isPair)([1, 2, 3]);
Currification
const keepEven = filter(isPair);
keepEven([1, 2, 3]);
Pipe
const numbers = [1, 2, 3, 2];
const result = numbers
|> filter(isPair)
|> map(double)
|> dedupe
(numbers)
([2, 2])
([4, 4])
fp-ts
Disclaimer. Teaching functional programming is out of scope of this project, so the documentation assumes you already know what FP is.
It includes the most popular data types, type classes, and abstractions from languages like Haskell, PureScript, and Scala.
const numbers = [1, 2, 3, 2];
const result = numbers
|> filter(isPair)
|> map(double)
|> dedupe
import * as A from 'fp-ts/Array';
import { pipe } from 'fp-ts/function';
const numbers = [1, 2, 3, 2];
const result = pipe(
numbers,
A.filter(isPair),
A.map(double),
dedupe,
);
import { pipe } from 'fp-ts/function';
import * as A from 'fp-ts/Array';
import * as NEA from 'fp-ts/NonEmptyArray';
Normes d'import
Modules
- Array
- NonEmptyArray
- Option
- Either
- Record
- Task
- Reader
- ...
Option
const findUser = (userId: number): User | undefined => {
// ...
};
const findUser = (userId: number): Option<User> => {
// ...
};
type Option<A> =
| { _tag: 'Some', value: A }
| { _tag: 'None' };
import * as O from 'fp-ts/Option';
const username = pipe(
userId,
findUser,
O.map(user => user.name)
);
Tous en boite !
Option : une boîte contenant zéro ou une valeur
Array : une boîte contenant zéro, une ou plusieurs valeurs du même type
NonEmptyArray : une boîte contenant une ou plusieurs valeurs du même type
map : transformer ce qu'il y a dans la boite
- Cloner le repository
-
npm install
-
npm run test
- Réactiver les test un à un
- Les faire passer au vert
Password Vegas2024
SSID DevfestSXB
Une boîte contenant une valeur d'un type ou d'un autre
Either
type Either<E, A> = Left<E> | Right<A>
Très souvent, le Either représente une erreur : soit tout est Right, soit on a une erreur en Left.
Une boîte qui contient ou contiendra une valeur
Task
type Task<A> = () => Promise<A>
Une Task ne peut pas échouer
Une boîte qui contient ou contiendra une valeur d'un type E ou d'un type A
TaskEither
type TaskEither<E, A> = () => Either<E, A>
Workshop fp-ts
By ereold
Workshop fp-ts
- 223