Skip to content

Instantly share code, notes, and snippets.

@kayac-chang
Created January 28, 2022 08:55
Show Gist options
  • Save kayac-chang/35a0cc952277e5eda8ef2bd2050d3d94 to your computer and use it in GitHub Desktop.
Save kayac-chang/35a0cc952277e5eda8ef2bd2050d3d94 to your computer and use it in GitHub Desktop.
[learn FP with Kirby using `fp-ts`] The Flow Operator
/**
* The Flow Operator
* ===
* The `flow` operator is almost same as `pipe` operator.
* The difference being the first argument must be a function, rather than value.
*/
import { flow, pipe } from "fp-ts/lib/function";
import assert = require("assert");
type Fn<A, B> = (a: A) => B;
type NumFn = Fn<number, number>;
const add1: NumFn = (num) => num + 1;
const mul2: NumFn = (num) => num * 2;
const toString = String;
describe(`1. code below is equivalent`, () => {
const result1 = pipe(1, add1, mul2);
const result2 = flow(add1, mul2)(1);
assert.ok(result1 === result2, "should be equal");
});
describe(`2. neither combine with each other, code should be equivalent too`, () => {
const result1 = pipe(1, flow(add1, mul2, toString));
const result2 = flow(add1, mul2, toString)(1);
assert.ok(result1 === result2, "should be equal");
});
/**
* We can model this behaviour using:
* ```
* (A -> B) -> (B -> C) -> (C -> D) -> (D -> E)
* ```
*/
type ConcatFn = (
a: number,
transformer: Fn<number, string>
) => [number, string];
const concat: ConcatFn = (a, transformer) => [a, transformer(a)];
describe(`3. The usecase of using flow instead of pipe`, () => {
concat(1, (n) => pipe(n, add1, mul2, toString)); // [1, '4']
// But we want to avoid using an anonymous function,
// which maybe shadowing a variable in outer scope.
concat(1, flow(add1, mul2, toString));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment