Skip to content

Instantly share code, notes, and snippets.

@gavinking
Last active December 26, 2015 06:39
Show Gist options
  • Save gavinking/7109759 to your computer and use it in GitHub Desktop.
Save gavinking/7109759 to your computer and use it in GitHub Desktop.
This demonstrates how we can abstract over tuple types of unknown length, without loss of typesafety, to do something useful, in this case, build comparator functions for tuple types.
/* Three generic functions for building tuple comparators. */
"A comparator function for any `Comparable` type."
Comparison comparator<Type>(Type x, Type y)
given Type satisfies Comparable<Type>
=> x<=>y;
"A comparator function for instances of `[]`."
Comparison emptyComparator([] x, [] y) => equal;
"Cons a comparator function with a tuple comparator,
producing a new tuple comparator."
Comparison tupleComparator<Type,Tail,Element>
(Comparison(Type,Type) headComparator, Comparison(Tail,Tail) tailComparator)
(Tuple<Type|Element,Type,Tail> x, Tuple<Type|Element,Type,Tail> y)
given Tail satisfies Element[] {
value comp = headComparator(x.first,y.first);
return comp!=equal then comp else tailComparator(x.rest, y.rest);
}
/* Now let's try it out! */
"A type alias to save some keypressing."
alias FSI => [Float, String, Integer];
"A comparator function for the tuple type
`[Float,String,Integer]`."
Comparison(FSI,FSI) compare =
tupleComparator(comparator<Float>,
tupleComparator(comparator<String>,
tupleComparator(comparator<Integer>,
emptyComparator)));
"Use the comparator function to sort some tuples."
void testTupleComparators() {
{FSI*} tuples = {[1.0, "a", 5], [1.0, "a", 1], [0.0, "a", 5], [0.0, "x", 2]};
printAll(tuples.sort(compare));
}
@trs123
Copy link

trs123 commented Oct 25, 2013

Nice!

Would it be possible to rewrite tupleComparator to use a tuple as argument (or varargs), so that one could write something similar to:

Comparison(FSI, FSI) compare = tupleComparator(comparator, comparator, comparator);

@gavinking
Copy link
Author

@trs123

No, unfortunately not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment