This repository has been archived on 2023-05-29. You can view files and clone it, but cannot push or open issues or pull requests.
fp-ts-training/src/exo0/exo0.ts

84 lines
3.0 KiB
TypeScript

// `fp-ts` training introduction
// Composing computations with `pipe` and `flow`
// Functional programming is all about composing small functions together like
// Lego bricks to build more and more complex computations.
//
// Strictly speaking, composing two functions `f` and `g` means applying the
// result of the first one to the second one. By applying this composition
// over and over you can chain multiple functions together.
//
// The `fp-ts` library provides helpers to do that:
// - `pipe` which first needs to be fed a value to start the pipe and then
// any number of functions to be applied sequentially.
// - `flow` which is the same thing but where we do not have to provide the
// first value. It will then return a function which will expect that value
// to be provided
//
// ```ts
// flow(f, g, h) === x => pipe(x, f, g, h)
// pipe(x, f, g, h) === flow(f, g, h)(x)
// ```
//
// NOTES:
// - `flow(f) === f`
// - `pipe(x, f) === f(x)`
import { flow, pipe } from "fp-ts/lib/function";
export const isEven = (value: number) => value % 2 === 0;
export const not = (value: boolean) => !value;
///////////////////////////////////////////////////////////////////////////////
// PIPE & FLOW //
///////////////////////////////////////////////////////////////////////////////
// For this exercise each function needs to be implemented using both forms:
// - a `pipe` implementation (P suffix)
// - a `flow` implementation (F suffix)
// Using only the two helpers `isEven` and `not` at the top of this file (and
// `pipe` or `flow`), write the function `isOdd` that checks if a number is
// odd.
export const isOddP: (value: number) => boolean = (value: number) =>
pipe(value, isEven, not);
export const isOddF: (value: number) => boolean = flow(isEven, not);
// We will write a function that for any given number, computes the next
// one according to the following rules:
// - if n is even => divide it by two
// - if n is odd => triple it and add one
//
// This sequence is the object of The Collatz conjecture: https://en.wikipedia.org/wiki/Collatz_conjecture
//
// Below is the functional equivalent of the control flow statement if-else.
export const ifThenElse =
<A>(onTrue: () => A, onFalse: () => A) => (condition: boolean) =>
condition ? onTrue() : onFalse();
// Using `pipe` and `ifThenElse`, write the function that computes the next step in the Collatz
// sequence.
const divideByTwo = (a: number): number => a / 2;
const triple = (a: number): number => a * 3;
const addOne = (a: number): number => a + 1;
const tripleAndAddOne = flow(triple, addOne);
export const next: (value: number) => number = (value) =>
ifThenElse(
() => divideByTwo(value),
() => tripleAndAddOne(value),
)(isEven(value));
// Using only `flow` and `next`, write the function that for any given number
// a_n from the Collatz sequence, returns the number a_n+3 (ie. the number
// three steps ahead in the sequence).
export const next3: (value: number) => number = flow(next, next, next);