Hi, Racket Discourse.
I have been thinking a lot about multisets recently, because I want to implement a particular "computer algebra" system which codifies arithmetic/algebra in terms of "closed-form numbers", to a degree, based on the work of William Bricken, et al. [0]
skip this part for the TL;DR
The basic idea is that you have three elementary "forms", denoted by:
(...)
analog to (exp ...)
;
[...]
analog to (log ...)
;
<...>
analog to (neg ...)
.
The exponential and logarithmic forms are typically interpreted in base e
, Euler's number, but they are in essence base-agnostic.
These forms act as containers which then have the usual arithmetical and algebraic rules:
(x) := #^x
[x] := log_#(x)
<x> := -x
where # is an arbitrary base.
Writing expressions next to each other is implied addition. Whole numbers can be written, e.g.,
0 := _ ;; (void)
1 := ()
2 := ()()
3 := ()()()
etc.
We may write the usual operations, like addition,
A+B := A B
and subtraction,
A-B := A<B>
where <<x>> := x
on to multiplication,
A*B := ([A][B])
and division,
A/B := ([A]<[B]>)
and exponentiation,
A^B := (([[A]][B]))
and so on.
There are a few axiomatic equations (3, if I recall correctly) that are used to establish the general properties of the system, and from which the rest of it can then be deduced.
It also introduces an interesting construction, which he simply calls J := [<()>]
(that he refers to as the additive imaginary, although πi
might be a more familiar characterization), analog to the imaginary number i
(multiplicative imaginary).
This can be used to "negate" an expression A
by way of (J [A])
, lessening somewhat the primacy of the <...>
form.
I am not a mathematician, so the full semantics of the above escapes me, but it has been on my mind quite often since I came upon it.
It is notable that the ordering of the content does not matter--only the multiplicity and containment relationship are significant--which makes for an interesting place to apply pattern matching.
Racket does not have "explicit" support for multisets, although there are libraries such as rebellion which do offer them as reified data structures.
The point of this whole digression, is to ask whether there is a particular reason not to use immutable hash-tables as multisets, where the keys themselves are immutable hash-tables, and their multiplicity is stored in the values of the keys?
One would have to differentiate between the different "types" of containers, but I reckon this can be done easily enough by using a special key in the hash-table which maps to itself, which indicates its "type", i.e. #hash(('EXP . 'EXP) ...)
[1] would be an exponential form, or something like that, obviously barring multiple such "special keys" in any given form.
I have seen that there have been recent discussions around the semantics/syntax of matching on hash-tables, as in this thread, which is why I ask, because I don't know much more about them than how to use them, for the most part.
[0] I have his texts on hand, but I am not sure about what the etiquette is regarding sharing that kind of thing, and the general idea is expounded upon in the texts linked on his site.
Edit:
[1] Or perhaps a gensym
key and type value, but you get the idea.