-
Notifications
You must be signed in to change notification settings - Fork 0
/
building-hyper-operations.js
47 lines (40 loc) · 2.01 KB
/
building-hyper-operations.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import {add, mul} from "./building-operations";
import {applyItNTimes, suc} from "./axiomatic-operations";
export let hyper = (n, a, b) => {
// There may be a way to extend the symmetry in the operation generation for n=1,0 but I haven't stumbled on it yet.
if (n === 0) {
return suc(a)(b)
}
if (n === 1) {
return add(a, b)
}
n--;
n--;
return hyperNFromMul(n, a, b);
};
// this is a factory that is needed to bind the current operation in a closure.
// Without it, the binary operations will have conflicting scopes
const binaryCurry = (op) => (a) => (b) => op(a, b);
// here we basically repeat the process that we used when generating operations, reusing the applyItNTimes method
// The difference is that rather than building a pipe for numbers to go through, we are instead building a pipe for
// operations to go through. Once consumed, the pipe will output the final binary operation that we need.
// The type signature that we need to pass to applyItNTimes for this to work is A, B -> A, B
const nextOperation = (binary) => {
const opA = binaryCurry(binary);
const repeatOpOfA = (a) => applyItNTimes(opA(a));
const repeatOpOfAByBTimes = (a) => (b) => repeatOpOfA(a)(b);
const repeatOpOfAByBTimesToIdentity = (a) => (b) => repeatOpOfAByBTimes(a)(b)(1);
return (a, b) => repeatOpOfAByBTimesToIdentity(a)(b);
};
export let hyperNFromMul = (n, a, b) => {
// Complete the pipeline for applyItNTimes.
// First comes the 'it'
let hyper = applyItNTimes(nextOperation);
// Then we supply the number of iterations to make. Each iteration will build the next hyper operation.
const hyperN = hyper(n);
// Just like we had to provide the identity when getting started with our applyItNTimes, we also need to supply the
// starting point for the hyper operation. In this case the starting point is an operation(mul) rather than a number
const hyperNFromMul = hyperN(mul);
// call our new operation and return the result
return hyperNFromMul(a, b)
};