add dict comparison function
This commit is contained in:
parent
48390b8556
commit
b4826605af
5 changed files with 57 additions and 24 deletions
|
|
@ -1,10 +1,8 @@
|
||||||
import { getInst, getType } from "../primitives/dynamic.js";
|
import { getInst, getType } from "../primitives/dynamic.js";
|
||||||
import { SymbolBool, SymbolChar, SymbolDouble, SymbolInt, SymbolType, SymbolUnit } from "../primitives/primitive_types.js";
|
import { SymbolBool, SymbolChar, SymbolDouble, SymbolInt, SymbolType, SymbolUnit } from "../primitives/primitive_types.js";
|
||||||
import { getHumanReadableName } from "../primitives/symbol.js";
|
|
||||||
import { symbolDict, symbolList, symbolProduct, symbolSet, symbolSum } from "../structures/type_constructors.js";
|
import { symbolDict, symbolList, symbolProduct, symbolSet, symbolSum } from "../structures/type_constructors.js";
|
||||||
import { capitalizeFirstLetter } from "../util/util.js";
|
|
||||||
import { compareBools, compareNumbers, compareStrings, compareUnits } from "./primitives.js";
|
import { compareBools, compareNumbers, compareStrings, compareUnits } from "./primitives.js";
|
||||||
import { compareLists, compareProducts, compareSets, compareSums } from "./structures.js";
|
import { compareDicts, compareLists, compareProducts, compareSets, compareSums } from "./structures.js";
|
||||||
import { compareTypes } from "./type.js";
|
import { compareTypes } from "./type.js";
|
||||||
|
|
||||||
const typeSymbolToCmp = new Map([
|
const typeSymbolToCmp = new Map([
|
||||||
|
|
@ -20,7 +18,7 @@ const typeSymbolToCmp = new Map([
|
||||||
[symbolProduct , compareProducts],
|
[symbolProduct , compareProducts],
|
||||||
[symbolSum , compareSums],
|
[symbolSum , compareSums],
|
||||||
[symbolSet , compareSets],
|
[symbolSet , compareSets],
|
||||||
// [symbolDict , compareDicts], TODO
|
[symbolDict , compareDicts],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const makeCompareFn = type => {
|
export const makeCompareFn = type => {
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
import { compareNumbers } from "./primitives.js"
|
import { compareNumbers } from "./primitives.js"
|
||||||
import { get, length as lengthLs } from "../structures/list.js";
|
import { get, length as lengthLs } from "../structures/list.js";
|
||||||
import { read, length as lengthSet } from "../structures/set.js";
|
import { read as readSet, length as lengthSet, first as firstSet } from "../structures/set.js";
|
||||||
import { newProduct, getLeft, getRight } from "../structures/product.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";
|
import { match } from "../structures/sum.js";
|
||||||
|
|
||||||
// (a -> a -> Int) -> [a] -> [a] -> Int
|
|
||||||
export const compareLists = compareElems => x => y => {
|
export const compareLists = compareElems => x => y => {
|
||||||
return compareNumbers(lengthLs(x))(lengthLs(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 => {
|
export const compareProducts = compareLeft => compareRight => x => y => {
|
||||||
return compareLeft (getLeft (x))(getLeft (y))
|
return compareLeft (getLeft (x))(getLeft (y))
|
||||||
|| compareRight(getRight(x))(getRight(y));
|
|| compareRight(getRight(x))(getRight(y));
|
||||||
};
|
};
|
||||||
|
|
||||||
// (a -> a -> Int) -> (b -> b -> Int) -> (a | b) -> (a | b) -> Int
|
|
||||||
export const compareSums = compareLeft => compareRight => x => y => {
|
export const compareSums = compareLeft => compareRight => x => y => {
|
||||||
// console.log("compareSums...", x, y)
|
// console.log("compareSums...", x, y)
|
||||||
return match(x)
|
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 => {
|
export const compareSets = compareElems => x => y => {
|
||||||
return compareNumbers(lengthSet(x))(lengthSet(y))
|
return compareNumbers(lengthSet(x))(lengthSet(y))
|
||||||
|| (() => {
|
|| (() => {
|
||||||
// sets have same size -> iterate over both sets and compare their elements pairwise
|
// 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
|
// because of the underlying red-black tree, iteration happens in ordered fashion
|
||||||
const iterate = iterX => iterY =>
|
const iterate = iterX => entryY =>
|
||||||
read(iterX)
|
match(readSet(iterX))
|
||||||
(keyX => nextX =>
|
(entryX =>
|
||||||
read(iterY)
|
match(readSet(entryY))
|
||||||
// we could also use the comparison function that is embedded in the set object,
|
(resultY => compareElems
|
||||||
// but to be consistent with the other comparison-functions, we don't.
|
(getLeft(entryX))
|
||||||
(keyY => nextY => compareElems(keyX)(keyY) || iterate(nextX)(nextY))
|
(getLeft(resultY))
|
||||||
(0)) // end of set y (we'll never get here because sets are same size)
|
|| iterate
|
||||||
(0); // end of set x
|
(getRight(entryX))
|
||||||
return iterate(first(x))(first(y));
|
(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));
|
||||||
})();
|
})();
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { getDefaultTypeParser } from "../parser/type_parser.js";
|
import { getDefaultTypeParser } from "../parser/type_parser.js";
|
||||||
import { compareLists, compareProducts, compareSets, compareSums } from "./structures.js";
|
import { compareDicts, compareLists, compareProducts, compareSets, compareSums } from "./structures.js";
|
||||||
|
|
||||||
const mkType = getDefaultTypeParser();
|
const mkType = getDefaultTypeParser();
|
||||||
|
|
||||||
|
|
@ -11,4 +11,6 @@ export const ModuleCompareStructures = [
|
||||||
{i: compareSums, t: mkType("∀a,b: (a -> a -> Int) -> (b -> b -> Int) -> (a+b) -> (a+b) -> Int")},
|
{i: compareSums, t: mkType("∀a,b: (a -> a -> Int) -> (b -> b -> Int) -> (a+b) -> (a+b) -> Int")},
|
||||||
|
|
||||||
{i: compareSets, t: mkType("∀a: (a -> a -> Int) -> {a} -> {a} -> Int")},
|
{i: compareSets, t: mkType("∀a: (a -> a -> Int) -> {a} -> {a} -> Int")},
|
||||||
|
|
||||||
|
{i: compareDicts, t: mkType("∀a,b: (a -> a -> Int) -> (b -> b-> Int) -> (a => b) -> (a => b) -> Int")}
|
||||||
];
|
];
|
||||||
|
|
@ -14,7 +14,12 @@ export const last = dict => dict.tree.end;
|
||||||
|
|
||||||
export const read = iter => {
|
export const read = iter => {
|
||||||
if (iter !== undefined && iter.valid) {
|
if (iter !== undefined && iter.valid) {
|
||||||
return newRight(newProduct(newProduct(iter.key)(iter.value))(iter.clone().next()));
|
return newRight(
|
||||||
|
newProduct(
|
||||||
|
newProduct(iter.key)(iter.value)
|
||||||
|
(iter.clone().next())
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return newLeft(unit);
|
return newLeft(unit);
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,11 @@ export const last = set => set.tree.end;
|
||||||
// test if iterator is 'done', and if not, get element and advance iterator.
|
// test if iterator is 'done', and if not, get element and advance iterator.
|
||||||
export const read = iter => {
|
export const read = iter => {
|
||||||
if (iter !== undefined && iter.valid) {
|
if (iter !== undefined && iter.valid) {
|
||||||
return newRight(newProduct(iter.key)(iter.clone().next()));
|
return newRight(
|
||||||
|
newProduct
|
||||||
|
(iter.key)
|
||||||
|
(iter.clone().next())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return newLeft(unit);
|
return newLeft(unit);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue