95 lines
3.6 KiB
JavaScript
95 lines
3.6 KiB
JavaScript
// Total ordering of composed types
|
|
|
|
import { compareNumbers, compareStrings } from "./primitives.js"
|
|
import { get, length as lengthLs } from "../structures/list.js";
|
|
import { read as readSet, length as lengthSet, first as firstSet } from "../structures/set.js";
|
|
import { read as readDict, length as lengthDict, first as firstDict } from "../structures/dict.js";
|
|
import { getLeft, getRight } from "../structures/product.js";
|
|
import { match } from "../structures/sum.js";
|
|
|
|
export const compareFunctions = _compareInput => _compareOutput => x => y => {
|
|
// dirty but does the job
|
|
return compareStrings(x.toString())(y.toString());
|
|
}
|
|
|
|
export const compareLists = compareElems => x => y => {
|
|
return compareNumbers(lengthLs(x))(lengthLs(y))
|
|
|| (() => {
|
|
for (let i=0; i<lengthLs(x); i++) {
|
|
const elemCmp = compareElems(get(x)(i))(get(y)(i));
|
|
if (elemCmp !== 0) {
|
|
return elemCmp;
|
|
}
|
|
}
|
|
return 0;
|
|
})();
|
|
};
|
|
|
|
export const compareProducts = compareLeft => compareRight => x => y => {
|
|
return compareLeft (getLeft (x))(getLeft (y))
|
|
|| compareRight(getRight(x))(getRight(y));
|
|
};
|
|
|
|
export const compareSums = compareLeft => compareRight => x => y => {
|
|
// console.log("compareSums...", x, y)
|
|
return match(x)
|
|
(leftValueX => match(y)
|
|
(leftValueY => compareLeft(leftValueX)(leftValueY)) // both are left
|
|
((_rightValueY) => {
|
|
// console.log("x is 'left' and y is 'right' => x < y")
|
|
return -1;
|
|
}) // x is 'left' and y is 'right' => x < y
|
|
)
|
|
(rightValueX => match(y)
|
|
(_leftValueY => {
|
|
// console.log("x is 'right' and y is 'left' => x > y");
|
|
return 1;
|
|
}) // x is 'right' and y is 'left' => x > y
|
|
(rightValueY => compareRight(rightValueX)(rightValueY)) // both are right
|
|
);
|
|
};
|
|
|
|
export const compareSets = compareElems => x => y => {
|
|
return compareNumbers(lengthSet(x))(lengthSet(y))
|
|
|| (() => {
|
|
// sets have same size -> iterate over both sets and compare their elements pairwise
|
|
// because of the underlying red-black tree, iteration happens in ordered fashion
|
|
const iterate = iterX => entryY =>
|
|
match(readSet(iterX))
|
|
(entryX =>
|
|
match(readSet(entryY))
|
|
(resultY => compareElems
|
|
(getLeft(entryX))
|
|
(getLeft(resultY))
|
|
|| iterate
|
|
(getRight(entryX))
|
|
(getRight(resultY)))
|
|
(_ => 0))
|
|
(_ => 0); // we made it, sets are equal
|
|
return iterate(firstSet(x))(firstSet(y));
|
|
})();
|
|
};
|
|
|
|
export const compareDicts = compareKeys => compareValues => x => y => {
|
|
return compareNumbers(lengthDict(x))(lengthDict(y))
|
|
|| (() => {
|
|
// dicts have same size -> iterate over both and compare their entries pairwise
|
|
// because of the underlying red-black tree, iteration happens in ordered fashion
|
|
const iterate = iterX => iterY =>
|
|
match(readDict(iterX))
|
|
(entryX =>
|
|
match(readDict(iterY))
|
|
(entryY => compareKeys
|
|
(getLeft(getLeft(entryX)))
|
|
(getLeft(getLeft(entryY)))
|
|
|| compareValues
|
|
(getRight(getLeft(entryX)))
|
|
(getRight(getLeft(entryY)))
|
|
|| iterate
|
|
(getRight(entryX))
|
|
(getRight(entryY)))
|
|
(_ => 0))
|
|
(_ => 0); // we made it, dicts are equal
|
|
return iterate(firstDict(x))(firstDict(y));
|
|
})();
|
|
};
|