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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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