New generic relations package

23 views
Skip to first unread message

Siddhartha Kasivajhula

unread,
Dec 6, 2019, 5:08:27 PM12/6/19
to Racket Users, George Neuner, Alexis King
Hi folks,
Hope everyone's having a relaxing start to the holiday season. I've written a package dealing with generic relations and types, just announcing it here in case anyone finds it useful.

https://docs.racket-lang.org/relation/index.html

The package provides generic versions of order relations like < and =, and algebraic operators like +, so that they work on any type that exhibits a structure appropriate for the operation. I think of this as a complement to something like data/collection, which when used together make the experience of writing Racket type-agnostic for the most common cases. Here are some examples:

> (< 1 2 3)

#t

> (< "apple" "banana" "cherry")

#t

> (= "apple" "APPLE")

#f

> (= #:key string-upcase "apple" "APPLE")

#t

> (.. "hi" " " "there")

"hi there"

> (+ #(1 2 3) #(1 2 3) #(1 2 3))

'#(3 6 9)

> (->list (stream 1 2 3))

'(1 2 3)

> (= #:key (.. even? ->number) "12" "20")

#t

> (min #:key length "apple" "pear" "strawberry")

"pear"


The #:key argument is worth noting as it allows you to provide a definition of equivalence, i.e. supporting arbitrary equivalence classes on the input type. This inclusion was inspired by a recent discussion on this list (cc @George Neuner ). I also included the /= relation for good measure :)

Performance wise I haven't really looked into optimizing it since it mostly dispatches to built-in interfaces, but from profiling at an arm's length using this package just to give an idea, it looks like the interfaces range about 1-4x slower than built-in type-specific relations.

Some next steps or pipe dreams could be:
- supporting "ring" style distributive operators like the usual * for generalized multiplication.
- looking into multi-dispatch, like what @Alexis talks about here, to make the implementation cleaner. This is probably a necessary prerequisite to...
- ... adding more algebraic datatypes as templates for generic interfaces (like the monoid or "composition-like" and group or "addition-like" interfaces already present)
- ... which could be useful in supporting linear algebra types and operations like the matrix operations in the math package
- more explicit treatment of order structures like lattices, supremums, infimums in the order relations so that you could do something like (sup <args>) and it would return a result using a standard supremum-finding algorithm across any types for which an order relation has been defined, for example (sup canid felid) ; => carnivora

This is my first Racket package, so feedback of any kind would be much appreciated. Thanks!

-Sid

Reply all
Reply to author
Forward
0 new messages