| Data Type | Si usa per |
|---|---|
| Option | Un valore che c'è o è null-ish |
| Either | Validazione o operazione che può fallire |
| TaskEither | Operazione asincrona che può fallire |
Last active
August 2, 2022 01:51
-
-
Save balanza/c9c0b7a5c7539eacba9859b1af8f1891 to your computer and use it in GitHub Desktop.
fp-ts didactic examples
This file contains hidden or 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
| type Option<A> = None | Some<A>; |
This file contains hidden or 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
| import * as O from "fp-ts/Option"; | |
| O.some(42); // { _tag: "Some", value: 42 } | |
| O.none; // // { _tag: "None" } | |
| declare const myVar: object; | |
| O.some(myVar); // { _tag: "Some", value: myVar } | |
| // ^^^^^ può essere null!! |
This file contains hidden or 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
| declare const myVar: object; | |
| O.fromNullable(myVar) // Option<object> | |
| // ^^^ può essere sia None che Some<object>, | |
| // a seconda del contenuto della variabile |
This file contains hidden or 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
| import * as O from "fp-ts/Option"; | |
| import * as E from "fp-ts/Either"; | |
| O.fromNullable // crea un Option da un valore | |
| E.fromNullable // crea un Either da un valore |
This file contains hidden or 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
| import * as O from "fp-ts/Option"; | |
| O.isSome | |
| O.isNone |
This file contains hidden or 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
| const maybeFoo = O.some("foo"); | |
| maybeFoo.value; | |
| // ^^^^ Build error: value non è definito per Option<string> | |
| if (O.isSome(maybeFoo)) { | |
| console.log(maybeFoo.value); // "foo" | |
| } else { | |
| console.error(maybeFoo.value); | |
| // ^^^^ Build error: value non è definito per None | |
| } |
This file contains hidden or 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
| const toEuro = (n: number): string => `€${n}`; | |
| const toMaybeEuro = O.map(toEuro); // "eleva" toEuro per funzionare con Option | |
| toMaybeEuro(O.some(42)); // { _tag: "Some", value: 42 } | |
| toMaybeEuro(O.none); // { _tag: "none" } |
This file contains hidden or 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
| import {pipe} from "fp-ts/function"; | |
| pipe( | |
| 42, | |
| O.some, | |
| O.map(toEuro) | |
| ); |
This file contains hidden or 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
| const applyDiscount = (perc: number) => | |
| (n: number): number => n * (1 - perc / 100); | |
| const toRounded = (digits: number) => | |
| (n: number): number => Math.round(n * 10 ** digits) / 10 ** digits; | |
| const toEuro = (n: number): string => `$${n}`; | |
| pipe( | |
| myPrice, | |
| O.fromNullable, | |
| O.map(applyDiscount(35)), | |
| O.map(toRounded(2)), | |
| O.map(toEuro) | |
| ); |
This file contains hidden or 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
| type Product = { name: string; price: number; }; | |
| const products = new Map<string, Product>(); | |
| const getFinalPrice = (productId: string): O.Option<string> => | |
| pipe( | |
| productId, | |
| O.fromPredicate(s => s.length > 0), // Un altro smart constructor! | |
| O.chain(id => { | |
| const product = products.get(id); | |
| return O.fromNullable(product; | |
| // equivalente di (product ? O.some(product) : O.none); | |
| }), | |
| O.map(product => product.price), | |
| O.map(applyDiscount(35)), | |
| O.map(toRounded(2)), | |
| O.map(toEuro) | |
| ); |
This file contains hidden or 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
| pipe( | |
| productId, | |
| getFinalPrice, | |
| O.fold( | |
| () => "Cannot find product, sorry :(", | |
| price => `You will pay ${price}` | |
| ) | |
| ) |
This file contains hidden or 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
| type Either<L, R> = Left<L> | Right<R> |
This file contains hidden or 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
| import * as E from "fp-ts/Either"; | |
| E.right(42); | |
| E.left("not 42"); | |
| const validatePrice = (price: number): E.Either<string, number> => | |
| price >= 0 | |
| ? E.right(price) | |
| : E.left("price cannot be negative") |
This file contains hidden or 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
| // a partire da un'istanza di Option | |
| pipe( | |
| 42, | |
| O.some, | |
| E.fromOption(() => "cannot handle null-ish values") | |
| ) | |
| // o da operazioni che possono fallire sollevando un'eccezione | |
| E.tryCatch( | |
| () => JSON.parse('{"baz":true}'), | |
| exception => new Error() | |
| ); |
This file contains hidden or 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
| const checkMinPrice = (price: number): E.Either<string, number> => | |
| price >= 10 // arbitrary threshold, just an example | |
| ? E.right(price) | |
| : E.left("price cannot be less than 10"); | |
| pipe( | |
| price, | |
| validatePrice, | |
| E.map(applyDiscount(23)), | |
| E.chain(checkMinPrice), | |
| E.fold( | |
| reason => new Error(reason), | |
| toEuro | |
| ) | |
| ); |
This file contains hidden or 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
| pipe( | |
| price, | |
| validatePrice, | |
| E.mapLeft(failure => new Error(`Validation error: ${failure}`)) | |
| E.map(applyDiscount) | |
| ); |
This file contains hidden or 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
| pipe( | |
| 1, // checkMinPrice fallirà | |
| validatePrice, | |
| E.mapLeft(failure => new Error(failure)), | |
| E.chain(checkMinPrice), | |
| E.mapLeft(failure => { | |
| // ^^^ Error | string | |
| // failure può arrivare sia da validatePrice che da checkMinPrice | |
| }) | |
| ); |
This file contains hidden or 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
| pipe( | |
| 1, | |
| validatePrice, | |
| E.mapLeft(failure => new Error(failure)), | |
| E.chain(price => | |
| pipe( | |
| price, | |
| checkMinPrice, | |
| E.mapLeft(failure => { | |
| // ^^^ failure può arrivare SOLO da checkMinPrice | |
| }) | |
| ) | |
| ) | |
| ); |
This file contains hidden or 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
| const fooOrError = E.right("foo"); | |
| if (E.isRight(fooOrError)) { | |
| console.log(fooOrError.right); | |
| console.log(fooOrError.left); | |
| // ^^^^ Build error: left non è definito per Right | |
| } else { | |
| console.log(fooOrError.left); | |
| console.log(fooOrError.right); | |
| // ^^^^ Build error: right è definito per Left | |
| } |
This file contains hidden or 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
| type Task<T> = () => Promise<T> | |
| type TaskEither<L, R> = () => Promise<Either<L, R>> |
This file contains hidden or 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
| import * as TE from "fp-ts/TaskEither"; | |
| const processPayment = async (price: number) => { | |
| return processPaymentOnProvider(); | |
| } | |
| const procedure = pipe( | |
| myPrice, | |
| validatePrice, | |
| TE.fromEither, | |
| TE.chain(actualPrice => | |
| TE.tryCatch( | |
| () => processPayment(actualPrice), | |
| err => "è successo qualcosa durante il pagamento" | |
| ) | |
| ), | |
| TE.map(_ => "OK"), | |
| TE.toUnion // una utility, di fatto una fold | |
| ); | |
| procedure().then(result => { | |
| console.log(result) | |
| }); |
| Operazione | Si usa per |
|---|---|
| type guard | type narrowing di un Data-Type in un sotto-tipo |
| smart constructor | Costruire un Data Type a partire da un valore o da un altro Data Type |
| map | Applicare una trasformazione al valore contenuto senza cambiare il sotto-tipo |
| chain | Applicare una trasformazione al valore contenuto cambiando il sotto-tipo |
| fold | Far convergere i due rami della computazione |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment