Conversation
Cofinite sets with one sentinel key — all set operations reduce to three map primitives (merge, keep, remove). No special types, no wrapper objects, no case explosion. Includes working Clojure implementation, verification of all four polarity combinations, and proofs of De Morgan's laws, identity elements, and self-complement properties.
There was a problem hiding this comment.
Pull request overview
Adds a new Clay/Kindly article describing a map-based representation for finite and cofinite (“negative”) sets using a sentinel key, and derives union/intersection/difference/complement via a small dispatch table over three map primitives.
Changes:
- New post file with Quarto metadata under
:clay/:quarto. - Introduces a sentinel-key encoding (
:neg) plus constructors/predicates. - Implements set operations via a 2×2 polarity dispatch and includes worked examples/verification tables.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ;; | Empty set | `{}` | | ||
| ;; | Universal set | `{:neg :neg}` | | ||
| ;; | Complement | Toggle `:neg` key | | ||
| ;; | Membership | pos: `get ≠ nil` · neg: `get = nil` | |
There was a problem hiding this comment.
The summary row for Membership says pos: get ≠ nil · neg: get = nil, but the implementation uses contains? (key presence). Using get is not equivalent when a set contains nil (or if values could ever be nil), since (get m nil) can’t distinguish “present with nil value” from “absent”. Suggest updating the summary to reflect contains?/find semantics (and, if desired, noting that get only works under the invariant value == key and key != nil).
| ;; | Membership | pos: `get ≠ nil` · neg: `get = nil` | | |
| ;; | Membership | pos: key present (`contains?` / `find`) · neg: key absent | |
There was a problem hiding this comment.
addressed in following commit
- Use map-* operations in table - specify contains? in Membership
This is a new article summarizing how to define negative sets as data and then how to work with them.