m-set-universe enum-set))) (make-enum-set universe (lset-difference eq? (enum-set->list universe) (enum-set-set enum-set))))) (define (enum-set-projection enum-set-1 enum-set-2) (make-enum-set (enum-set-universe enum-set-2) (lset-intersection eq? (enum-set-set enum-set-1) (enum-set->list (enum-set-universe enum-set-2))))) (define-syntax define-enumeration (syntax-rules () ((_ type-name (symbol ...) constructor-syntax) (begin (define-syntax type-name (lambda (s) (syntax-case s () ((type-name sym) (if (memq (syntax->datum #'sym) '(symbol ...)) #'(quote sym) (syntax-violation (symbol->string 'type-name) "not a member of the set" #f)))))) (define-syntax constructor-syntax (lambda (s) (syntax-case s () ((_ sym (... ...)) (let* ((universe '(symbol ...)) (syms (syntax->datum #'(sym (... ...)))) (quoted-universe (datum->syntax s (list 'quote universe))) (quoted-syms (datum->syntax s (list 'quote syms)))) (or (every (lambda (x) (memq x universe)) syms) (syntax-violation (symbol->string 'constructor-syntax) "not a subset of the universe" #f)) #`((enum-set-constructor (make-enumeration #,quoted-universe)) #,quoted-syms)))))))))) )