#lang racket
;; Total Order ADT used by Ordered Set ADT
;; Must provide:
;; a membership predicate
;; a total order
;; min and max functions with identities
;; user-defined associative operator and identity
;;
;; any other operations required by the user
;; e.g. to-hide and to-unhide
(provide to? to< to<= to> to> to>= to= to!= to-min to-min-ident
to-max to-max-ident to-op to-op-ident to-hide to-unhide)
;; For this example, we use a number hidden in a struct
(define-struct to-rep (hidden ) #:transparent)
(define (to-unhide x) (to-rep-hidden x))
(define (to-hide x) (make-to-rep x))
;; membership predicate
(define (to? x) (and (to-rep? x) (or (string? (to-rep-hidden x))(number? (to-rep-hidden x)))))
;; defining relation must be total, reflexive, transitive
(define (to<= a b)
(cond
[(equal? (to-rep-hidden a) "?") #t]
[(equal? (to-rep-hidden b) "+inf.0") #t]
[(equal? (to-rep-hidden a) "+inf.0") #f]
[(equal? (to-rep-hidden b) "?") #f]
[(and (number? (string->number (to-rep-hidden a))) (number? (string->number (to-rep-hidden b))))
(<= (string->number (to-rep-hidden a)) (string->number (to-rep-hidden b)))]
[else (string<=? (to-rep-hidden a) (to-rep-hidden b))]))
;; derived relations
(define (to> a b) (not (to<= a b)))
(define (to= a b) (and (to<= a b) (to<= b a)))
(define (to>= a b) (to<= b a))
(define (to< a b) (to> b a))
(define (to!= a b) (not (to= a b)))
;; min/max functions and identities
(define (to-min a b) (if (to< a b) a b))
(define to-min-ident (make-to-rep "+inf.0"))
(define (to-max a b) (if (to< a b) b a))
(define to-max-ident (make-to-rep "?"))
;; user-defined associative operator and identity
;; for this example we just add the secret numbers
(define (to-op a b)
(cond
[(and (string? a) (string? b)) (to-hide (string-append (to-rep-hidden a) (to-rep-hidden b)))]
[else (to-hide (string-append (to-rep-hidden a) (to-rep-hidden b)))]))
(define to-op-ident (to-hide ""))