Rebus is a tiny PureScript library that gives a visually mnemonic identity to data that is otherwise hard to confirm, by eye, as being the same data — while keeping a typeable text form and a speakable one, so the identity survives a filename, a search box and a screen reader.
But a pile of anonymous captures is unusable, because nothing in it can be recognised,
referred to, or typed. So every capture gets an identity derived from its own content,
immediately and for free: an ordered run of coloured icons — red cow, blue
star — spelled by a hyphenated alias, cow-ambulance. Naming becomes a
later, optional promotion rather than a toll on the way in.
Identical content lands on the identical run, which is deduplication for nothing; a real edit avalanches to a visibly different picture. Runs rather than single icons because an absurd juxtaposition is far easier to hold than any lone shape — and because 64 icons are only 64 identities, which is nothing.
Canonical text, as a sequencer prints it: MIDI note numbers, comma-separated within a chord, space-separated between them. Find the pair by reading. Then look at the right-hand column, which is the same question answered in one glance.
Each icon's colour is a hash of its own name, never of the content — so cow
is always red and star always blue. That is what makes the alias lossless:
a rebus rebuilt from the thirteen typed characters of cow-ambulance draws
identically to one computed live from the content.
A rebus is only an identity if no two of the things it distinguishes collide. The right-hand column is measured live, in this page, by minting a rebus for each of 289 project ids and counting the groups that came out sharing one alias.
| Width | Identities available | Colliding groups | Rebus of 160 |
|---|
Width two is not a bad hash: even a perfect one expects about ten collisions putting 289 items into 4,032 buckets. That is the birthday problem, and it arrives far earlier than intuition says. Dozens of things → two icons. Hundreds to a few thousand → three. Five is the ceiling, deliberately: past four the mnemonic stops being one absurd image and becomes a list to recite.
An index into this list is what a content hash actually produces, so the deck is fixed and append-only: reordering an entry would silently re-identify every rebus ever minted. The colours are not like that — colour is a memorability accent, and recolouring is a visual change rather than a migration.
rebusOf (chordsOf [[42,61,66,70,78],[46,58,65,72,74,79]])
== { icons: [ { icon: "bug", color: "hsl(188, 62%, 32%)" }
, { icon: "dog", color: "hsl(214, 62%, 44%)" } ]
, alias: "bug-dog"
}
rebusOfTextWidth Three "marginalia:160" -- three icons, for a set of hundreds
rebusFromAnyAlias "bug-dog" -- back from the typed characters
sessionAliasOf 41 -- a container: seeded, and a triple
Mapping those names onto FontAwesome classes, SVG symbols, ANSI escapes or a plotter is the
consumer's business. Dependencies are prelude, arrays,
strings, maybe. Nothing else.