add dict comparison function

This commit is contained in:
Joeri Exelmans 2025-05-07 14:05:57 +02:00
parent 48390b8556
commit b4826605af
5 changed files with 57 additions and 24 deletions

View file

@ -2,11 +2,11 @@
import { compareNumbers } from "./primitives.js"
import { get, length as lengthLs } from "../structures/list.js";
import { read, length as lengthSet } from "../structures/set.js";
import { newProduct, getLeft, getRight } from "../structures/product.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";
// (a -> a -> Int) -> [a] -> [a] -> Int
export const compareLists = compareElems => x => y => {
return compareNumbers(lengthLs(x))(lengthLs(y))
|| (() => {
@ -20,13 +20,11 @@ export const compareLists = compareElems => x => y => {
})();
};
// (a -> a -> Int) -> (b -> b -> Int) -> (a, b) -> (a, b) -> Int
export const compareProducts = compareLeft => compareRight => x => y => {
return compareLeft (getLeft (x))(getLeft (y))
|| compareRight(getRight(x))(getRight(y));
};
// (a -> a -> Int) -> (b -> b -> Int) -> (a | b) -> (a | b) -> Int
export const compareSums = compareLeft => compareRight => x => y => {
// console.log("compareSums...", x, y)
return match(x)
@ -46,21 +44,47 @@ export const compareSums = compareLeft => compareRight => x => y => {
);
};
// (a -> a -> Int) -> {a} -> {a} -> Int
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 => iterY =>
read(iterX)
(keyX => nextX =>
read(iterY)
// we could also use the comparison function that is embedded in the set object,
// but to be consistent with the other comparison-functions, we don't.
(keyY => nextY => compareElems(keyX)(keyY) || iterate(nextX)(nextY))
(0)) // end of set y (we'll never get here because sets are same size)
(0); // end of set x
return iterate(first(x))(first(y));
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));
})();
};