I suppose it could always be done via #:when but that feels like cheating, and it doesn't allow for decomposing a set that contains non-primitive values.
(struct cell (value candidates) #:transparent)
(match (cell #f (set 1 2 4 8 9))
[(cell _ cands) #:when (set-member? cands 4)
"cell can have a value of 4"]
[else "nope"])
;; "cell can have a value of 4"
For context, I'm working on a sudoku-making program and I was going to use a system where cell is a struct that contains, among other things, the remaining candidates for that cell. This would allow me to use match to determine if the cell has a specific candidate.
Making a match expander that will pattern match on all of the elements of the set is not too bad. A problem I have with this solution is that it copies the set into a list to make a match.
(define-match-expander set^
(syntax-parser
[(_ pat ...)
#'(? set? (app set->list (list-no-order pat ...)))]))
(match (set 3 2 1)
[(set^ 1 2 3) 'ok]
[_ 'nope])
;; => 'ok
(match (set 'y 'x 'z)
[(set^ a b c) (list a b c)]
[_ #f])
;; => '(x y z)
The previous expander could be modified slightly to match a subset. A better (IMO) expander that matches a subset of values (not patterns) can also be done like this:
(define-match-expander subset^-aux
(syntax-rules ()
[(_ v) (? (λ (s) (set-member? s v)))]
[(_ v . vs) (? (λ (s) (set-member? s v))
(subset^-aux . vs))]))
(define-match-expander subset^
(syntax-rules ()
[(_ v ...) (? set? (subset^-aux v ...))]))
(match (for/set ([i 100]) i)
[(subset^ 100) 'nope]
[(subset^ 45 80 90) 'ok]
[_ 'wha])
;; => 'ok