#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 ""))
