Skip to content

Instantly share code, notes, and snippets.

@zaetrik
zaetrik / apply-ap-example.ts
Last active May 9, 2020 13:30
Apply ap() example
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>;
}
@zaetrik
zaetrik / currying-example.ts
Created May 9, 2020 07:40
Currying Example
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
}
}
@zaetrik
zaetrik / applicative-type-class.ts
Created May 6, 2020 13:25
Applicative Type Class
// 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>
}
@zaetrik
zaetrik / apply-type-class.ts
Last active May 9, 2020 09:25
Apply Type Class
// 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)
@zaetrik
zaetrik / functor-option.ts
Last active May 5, 2020 14:17
Functor Option
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
};
@zaetrik
zaetrik / function-composition-lift.ts
Last active May 6, 2020 13:07
Function Composition Lift
// 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> {
@zaetrik
zaetrik / function-composition-problem.ts
Last active May 5, 2020 13:26
Function Composition Problem
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
@zaetrik
zaetrik / function-composition.ts
Last active May 5, 2020 12:24
Function Composition
// 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
@zaetrik
zaetrik / monoid-example-use-case.ts
Created May 4, 2020 13:41
Monoid Type Class Example Use Case
// 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";
@zaetrik
zaetrik / Monoid-option.ts
Created May 4, 2020 13:21
Monoid Type Class Option
// 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>> {