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/lib/Option"; | |
interface OptionFunctor { | |
map: <A, B>(fa: O.Option<A>, f: (a: A) => B) => O.Option<B>; | |
} | |
interface OptionApply extends OptionFunctor { | |
ap: <A, B>(fab: O.Option<(a: A) => B>, fa: O.Option<A>) => O.Option<B>; | |
} |
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 add = (x, y) => x + y | |
const addCurried = (x) => (y) => x + y | |
// Or to make it more clear we can write it like this => | |
function takeInFirstParameter(x) { | |
return function takeInSecondParameter(y) { | |
return x + y | |
} | |
} |
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
// The Applicative type class simply extends Apply with an `of` method turns A into F<A> | |
interface Applicative<F> extends Apply<F> { | |
of: <A>(a: A) => F<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
// Apply extends the Functor type class | |
// the `ap` method is able to unpack a function (a: A) => B that is wrapped inside a Functor instance | |
// and then `ap` uses `map` with the unpacked function to apply the function to another Functor | |
interface Apply<F> extends Functor<F> { | |
ap: <A, B>(fab: F<(a: A) => B>, fa: F<A>) => F<B> | |
} | |
// Under the hood `ap` looks something like this (where `apply` is the general Apply constructor): | |
// ap: (fab: F<(a: A) => B>, fa) => apply.map(fa, fab.value) |
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/lib/Option"; | |
const MyOptionFunctor = { | |
map: (option: O.Option<unknown>, f: (a: unknown) => unknown) => | |
O.isNone(option) ? O.none : O.some(f(option.value)), | |
// We check if 'option' is 'none' | |
// if so return 'none' | |
// else take out the value from 'option' and apply it to our function 'f' | |
// then wrap it in an 'Option' again | |
}; |
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
// Taken from https://dev.to/gcanti/getting-started-with-fp-ts-functor-36ek | |
// Here we lift a pure function to work with Array | |
function lift<B, C>(g: (b: B) => C): (fb: Array<B>) => Array<C> { | |
return fb => fb.map(g) | |
} | |
import { Option, isNone, none, some } from 'fp-ts/lib/Option' | |
// Here we lift a pure function to work with Option | |
function lift<B, C>(g: (b: B) => C): (fb: Option<B>) => Option<C> { |
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/lib/Option"; | |
const add = (x: number, y: number): O.Option<number> => x > 0 ? O.some(x + y) : O.none | |
const say = (x: number) => `Your number is ${x}` | |
// How can we compose add() with say()? | |
// add() returns an effect => Option<number> and say() takes in a type of number | |
// The input and output types do not match and therefore we cannot compose them |
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
// Function composition is the process of building more complex functions from simpler ones | |
const add = (x: number, y: number) => x + y | |
const say = (x: number) => `Your number is ${x}` | |
// Let's compose our two functions to build something more complex | |
const sayAddResult = (x: number, y: number) => say(add(x, y)) | |
sayAddResult(2, 5) // Your number is 7 |
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
// The use cases for Monoids & Semigroups are pretty similar | |
// Not every Semigroup can be a Monoid, e.g. when there is no neutral value for empty | |
// An example use case for both Semigroups & Monoids | |
// We merge two objects together we merge them by always using the right-most non-None value | |
// We do this by using the getLastMonoid function from fp-ts | |
// Mostly taken from https://dev.to/gcanti/getting-started-with-fp-ts-monoid-ja0 | |
import { getStructMonoid } from "fp-ts/lib/Monoid"; | |
import { Option } from "fp-ts/lib/Option"; |
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
// When we can find a Monoid instance for A we can create one for Option<A> | |
// When we take a look at the fp-ts implementation it will become clearer | |
export function getApplySemigroup<A>(S: Semigroup<A>): Semigroup<Option<A>> { | |
return { | |
concat: (x, y) => (isSome(x) && isSome(y) ? some(S.concat(x.value, y.value)) : none) | |
} | |
} | |
export function getApplyMonoid<A>(M: Monoid<A>): Monoid<Option<A>> { |