Last active
April 8, 2024 14:09
-
-
Save jeroenvanwijgerden/1435d87aae4729b79196598e9588aed3 to your computer and use it in GitHub Desktop.
chain.ts
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 Compose = { | |
<A, B>( | |
fn1: (x: A) => B | |
): (arg: A) => B; | |
<A, B, C>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C | |
): (arg: A) => C; | |
<A, B, C, D>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D | |
): (arg: A) => D; | |
<A, B, C, D, E>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E | |
): (arg: A) => E; | |
<A, B, C, D, E, F>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F | |
): (arg: A) => F; | |
<A, B, C, D, E, F, G>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G | |
): (arg: A) => G; | |
<A, B, C, D, E, F, G, H>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H | |
): (arg: A) => H; | |
<A, B, C, D, E, F, G, H, I>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I | |
): (arg: A) => I; | |
<A, B, C, D, E, F, G, H, I, J>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J | |
): (arg: A) => J; | |
<A, B, C, D, E, F, G, H, I, J, K>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K | |
): (arg: A) => K; | |
<A, B, C, D, E, F, G, H, I, J, K, L>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L | |
): (arg: A) => L; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M | |
): (arg: A) => M; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N | |
): (arg: A) => N; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N, | |
fn14: (x: N) => O | |
): (arg: A) => O; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N, | |
fn14: (x: N) => O, | |
fn15: (x: O) => P | |
): (arg: A) => P; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>( | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N, | |
fn14: (x: N) => O, | |
fn15: (x: O) => P, | |
fn16: (x: P) => Q | |
): (arg: A) => Q; | |
}; | |
const compose: Compose = (...fns: ((arg: any)=>any)[]) => { | |
return (initial: any) => fns.reduce((acc, fn) => fn(acc), initial); | |
} | |
type Chain = { | |
<A>( | |
initialValue: A | |
): A; | |
<A, B>( | |
initialValue: A, | |
fn1: (x: A) => B | |
): B; | |
<A, B, C>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C | |
): C; | |
<A, B, C, D>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D | |
): D; | |
<A, B, C, D, E>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E | |
): E; | |
<A, B, C, D, E, F>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F | |
): F; | |
<A, B, C, D, E, F, G>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G | |
): G; | |
<A, B, C, D, E, F, G, H>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H | |
): H; | |
<A, B, C, D, E, F, G, H, I>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I | |
): I; | |
<A, B, C, D, E, F, G, H, I, J>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J | |
): J; | |
<A, B, C, D, E, F, G, H, I, J, K>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K | |
): K; | |
<A, B, C, D, E, F, G, H, I, J, K, L>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L | |
): L; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M | |
): M; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N | |
): N; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N, | |
fn14: (x: N) => O | |
): O; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N, | |
fn14: (x: N) => O, | |
fn15: (x: O) => P | |
): P; | |
<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q>( | |
initialValue: A, | |
fn1: (x: A) => B, | |
fn2: (x: B) => C, | |
fn3: (x: C) => D, | |
fn4: (x: D) => E, | |
fn5: (x: E) => F, | |
fn6: (x: F) => G, | |
fn7: (x: G) => H, | |
fn8: (x: H) => I, | |
fn9: (x: I) => J, | |
fn10: (x: J) => K, | |
fn11: (x: K) => L, | |
fn12: (x: L) => M, | |
fn13: (x: M) => N, | |
fn14: (x: N) => O, | |
fn15: (x: O) => P, | |
fn16: (x: P) => Q | |
): Q; | |
}; | |
// You would think (hope) that `chain` could be implemented using `compose`, but typechecking isn't smart enough yet. | |
const chain: Chain = (initial: any, ...fns: ((arg: any)=>any)[]) => { | |
return fns.reduce((acc, fn) => fn(acc), initial); | |
}; | |
// For a function F that produces a side-effect involving its single parameter X but does not return X; | |
// you can wrap F in `link`, adapting it so X is returned. | |
// Note: type A will primarily be determined by F. If F specified a type for its first parameter, | |
// then A will become that type. Because of this, unfortunately something like | |
// link(console.log) | |
// will be seen as returning an `any` type. | |
// If F does not explicitly provide a type for its parameter, then A will be inferred from the usage of | |
// the function returned by link (the adapted version of F). | |
export const link = <A>(f: (arg: A) => unknown) => { | |
return (value: A) => { | |
f(value); | |
return value | |
}; | |
}; | |
/* | |
chain( | |
[1,2,3], | |
link(x=>x.push(1)), | |
x=>x.length | |
) | |
chain( | |
[1,2,3], | |
compose( | |
link(x=>x.push(4)), | |
x=>x.length | |
) | |
) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment