Fix except/e and add append mode for disj-sum/e

This commit is contained in:
Max New 2013-11-10 01:48:34 -06:00
parent 562cecd10c
commit 6d02da0f2b
7 changed files with 275 additions and 204 deletions

View File

@ -7,6 +7,7 @@
"enumerator.rkt"
"env.rkt"
"error.rkt"
"lang-struct.rkt"
"match-a-pattern.rkt"
"preprocess-pat.rkt"
@ -22,7 +23,6 @@
[lang-enum? (-> any/c boolean?)]
[enum? (-> any/c boolean?)]))
(struct lang-enum (enums unused-var/e))
(struct repeat (n terms) #:transparent)
(struct name-ref (name) #:transparent)
@ -34,33 +34,33 @@
(define (lang-enumerators lang)
(define l-enums (make-hash))
(define unused-var/e
(except/e var/e
(used-vars lang)))
(define (enumerate-lang cur-lang enum-f)
(apply except/e
var/e
(used-vars lang)))
(define (enumerate-lang! cur-lang enum-f)
(for ([nt (in-list cur-lang)])
(hash-set! l-enums
(nt-name nt)
(with-handlers ([exn:fail? fail/e])
(enum-f (nt-rhs nt)
l-enums)))))
(let-values ([(fin-lang rec-lang)
(sep-lang lang)])
(enumerate-lang fin-lang
(λ (rhs enums)
(enumerate-rhss rhs enums unused-var/e)))
(enumerate-lang rec-lang
(λ (rhs enums)
(thunk/e +inf.f
(λ ()
(enumerate-rhss rhs enums unused-var/e)))))
(nt-name nt)
(with-handlers ([exn:fail:redex? fail/e])
(enum-f (nt-rhs nt)
l-enums)))))
(define-values (fin-lang rec-lang) (sep-lang lang))
(enumerate-lang! fin-lang
(λ (rhs enums)
(enumerate-rhss rhs enums unused-var/e)))
(enumerate-lang! rec-lang
(λ (rhs enums)
(thunk/e +inf.f
(λ ()
(enumerate-rhss rhs enums unused-var/e)))))
(lang-enum l-enums unused-var/e)))
(lang-enum l-enums unused-var/e))
(define (pat-enumerator l-enum pat)
(map/e
fill-refs
(λ (_)
(error 'pat-enum "Enumerator is not a bijection"))
(redex-error 'pat-enum "Enumerator is not a bijection"))
(pat/e pat
(lang-enum-enums l-enum)
(lang-enum-unused-var/e l-enum))))
@ -96,7 +96,7 @@
[`boolean bool/e]
[`variable var/e]
[`(variable-except ,s ...)
(except/e var/e s)]
(apply except/e var/e s)]
[`(variable-prefix ,s)
;; todo
(unimplemented "var-prefix")]
@ -204,13 +204,38 @@
(f x))))
;; Base Type enumerators
(define natural/e nats)
(define natural/e nats/e)
(define (between? x low high)
(and (>= x low)
(<= x high)))
(define (range-with-pred/e-p low high)
(cons (range/e low high)
(λ (n) (between? n low high))))
(define low/e-p
(range-with-pred/e-p #x61 #x7a))
(define up/e-p
(range-with-pred/e-p #x41 #x5a))
(define bottom/e-p
(range-with-pred/e-p #x0 #x40))
(define mid/e-p
(range-with-pred/e-p #x5b #x60))
(define above1/e-p
(range-with-pred/e-p #x7b #xd7FF))
(define above2/e-p
(range-with-pred/e-p #xe000 #x10ffff))
(define char/e
(map/e
integer->char
char->integer
(range/e #x61 #x7a)))
(disj-sum/e #:append? #t
low/e-p
up/e-p
bottom/e-p
mid/e-p
above1/e-p
above2/e-p)))
(define string/e
(map/e
@ -219,10 +244,11 @@
(many/e char/e)))
(define integer/e
(disj-sum/e (cons nats (λ (n) (>= n 0)))
(disj-sum/e #:alternate? #t
(cons nats/e (λ (n) (>= n 0)))
(cons (map/e (λ (n) (- (+ n 1)))
(λ (n) (- (- n) 1))
nats)
nats/e)
(λ (n) (< n 0)))))
;; This is really annoying so I turned it off
@ -241,7 +267,8 @@
(many1/e char/e)))
(define base/e
(disj-sum/e (cons (const/e '()) null?)
(disj-sum/e #:alternate? #t
(cons (const/e '()) null?)
(cons num/e number?)
(cons string/e string?)
(cons bool/e boolean?)
@ -250,11 +277,6 @@
(define any/e
(fix/e +inf.f
(λ (any/e)
(disj-sum/e (cons base/e (negate pair?))
(disj-sum/e #:alternate? #t
(cons base/e (negate pair?))
(cons (cons/e any/e any/e) pair?)))))
(define (unsupported pat)
(error 'generate-term "#:i-th does not support ~s patterns" pat))
(define (unimplemented pat)
(error 'generate-term "#:i-th does not yet support ~s patterns" pat))

View File

@ -1,10 +1,15 @@
#lang racket/base
(require racket/math
racket/match
racket/list
(require racket/bool
racket/contract
racket/function
racket/list
racket/math
racket/match
racket/promise
data/gvector)
data/gvector
"error.rkt")
(provide enum
enum?
@ -34,14 +39,11 @@
to-list
take/e
drop/e
fold-enum
display-enum
nats
nats/e
range/e
nats+/e
)
nats+/e)
;; an enum a is a struct of < Nat or +Inf, Nat -> a, a -> Nat >
(struct enum
@ -53,14 +55,16 @@
(enum-size e))
;; decode : enum a, Nat -> a
(define (decode e n)
(define/contract (decode e n)
(-> enum? exact-nonnegative-integer? any/c)
(if (and (< n (enum-size e))
(>= n 0))
((enum-from e) n)
(error 'out-of-range)))
(redex-error 'decode "Index into enumerator out of range")))
;; encode : enum a, a -> Nat
(define (encode e a)
(define/contract (encode e a)
(-> enum? any/c exact-nonnegative-integer?)
((enum-to e) a))
;; Helper functions
@ -96,30 +100,30 @@
(λ (x) (encode e x))))
;; except/e : enum a, a -> enum a
(define (except/e e excepts)
(cond [(empty? excepts) e]
[else
(except/e
(begin
(with-handlers ([exn:fail? (λ (_) e)])
(let ([m (encode e (car excepts))])
(enum (- (size e) 1)
(λ (n)
(if (< n m)
(decode e n)
(decode e (+ n 1))))
(λ (x)
(let ([n (encode e x)])
(cond [(< n m) n]
[(> n m) (- n 1)]
[else (error 'excepted)])))))))
(cdr excepts))]))
;; Everything inside e MUST be in the enumerator or you will get a redex-error
(define (except/e e . excepts)
(define (except1/e x e)
(cond [(= (size e) 0) e]
[else
(define xi (encode e x))
(define (from-nat n)
(cond [(< n xi) (decode e n)]
[else (decode e (add1 n))]))
(define (to-nat y)
(define yi (encode e y))
(cond [(< yi xi) yi]
[(> yi xi) (sub1 yi)]
[else (redex-error 'encode "attempted to encode an excepted value")]))
(enum (max 0 (sub1 (size e))) from-nat to-nat)]))
(foldr except1/e
e
excepts))
;; to-list : enum a -> listof a
;; better be finite
(define (to-list e)
(when (infinite? (size e))
(error 'too-big))
(redex-error 'to-list "cannot encode an infinite list"))
(map (enum-from e)
(build-list (size e)
identity)))
@ -128,31 +132,17 @@
;; returns an enum of the first n parts of e
;; n must be less than or equal to size e
(define (take/e e n)
(unless (or (infinite? (size e))
(<= n (size e)))
(error 'too-big))
(unless (or (<= n (size e)))
(redex-error 'take/e "there aren't ~s elements in ~s" n e))
(enum n
(λ (k)
(unless (< k n)
(error 'out-of-range))
(decode e k))
(λ (x)
(let ([k (encode e x)])
(unless (< k n)
(error 'out-of-range))
(redex-error 'take/e "attempted to encode an element not in an enumerator"))
k))))
;; drop/e : enum a, Nat -> enum a
(define (drop/e e n)
(unless (or (infinite? (size e))
(<= n (size e)))
(error 'too-big))
(enum (- (size e) n)
(λ (m)
(decode e (+ n m)))
(λ (x)
(- (encode e x) n))))
;; display-enum : enum a, Nat -> void
(define (display-enum e n)
(for ([i (range n)])
@ -162,9 +152,9 @@
(define empty/e
(enum 0
(λ (n)
(error 'empty))
(redex-error 'decode "absurd"))
(λ (x)
(error 'empty))))
(redex-error 'encode "no elements in the enumerator"))))
(define (const/e c)
(enum 1
@ -173,7 +163,7 @@
(λ (x)
(if (equal? c x)
0
(error 'bad-val)))))
(redex-error 'encode "value not in enumerator")))))
;; from-list/e :: Listof a -> Gen a
;; input list should not contain duplicates
@ -191,20 +181,12 @@
(λ (x)
(hash-ref rev-map x)))))
;; take-while : Listof a, (a -> bool) -> Listof a
(define (take-while l pred)
(cond [(empty? l) (error 'empty)]
[(not (pred (car l))) '()]
[else
(cons (car l)
(take-while (cdr l) pred))]))
(define nats
(define nats/e
(enum +inf.f
identity
(λ (n)
(unless (>= n 0)
(error 'out-of-range))
(redex-error 'encode "Not a natural"))
n)))
(define ints/e
(enum +inf.f
@ -284,51 +266,70 @@
(map-pairs/even (cdr l)))))
(apply sum/e (map-pairs sum/e identity (list* a b c rest)))]))
(define (disj-sum/e e-p . e-ps)
(define (disj-sum/e #:alternate? [alternate? #f] #:append? [append? #f] e-p . e-ps)
(define/match (disj-sum2/e e-p1 e-p2)
[((cons e1 1?) (cons e2 2?))
;; Sum two enumerators of different sizes
(define (sum-uneven less/e less? more/e more?)
(define (alternate-uneven less/e less? more/e more? #:less-first? less-first?)
(define-values (first/e second/e)
(if less-first?
(values less/e more/e)
(values more/e less/e)))
;; interleave until less/e is exhausted
;; pairsdone is 1+ the highest index using less/e
(define less-size (size less/e))
(define pairsdone (* 2 less-size))
(define (from-nat n)
(if (< n pairsdone)
(let-values ([(q r) (quotient/remainder n 2)])
;; Always put e1 first though!
(decode (match r
[0 e1]
[1 e2])
q))
(decode more/e (- n less-size))))
(cond [(< n pairsdone)
(define-values (q r) (quotient/remainder n 2))
;; Always put e1 first though!
(decode (match r
[0 first/e]
[1 second/e])
q)]
[else (decode more/e (- n less-size))]))
(define (to-nat x)
(cond [(less? x)
(* 2 (encode less/e x))]
(+ (* 2 (encode less/e x))
(if less-first? 0 1))]
[(more? x)
(define i (encode more/e x))
(if (< i less-size)
(+ (* 2 i) 1)
(+ (* 2 i)
(if less-first? 1 0))
(+ (- i less-size) pairsdone))]
[else (error "bad term")]))
[else (redex-error 'encode "bad term")]))
(enum (+ less-size (size more/e))
from-nat
to-nat))
to-nat))
(define s1 (size e1))
(define s2 (size e2))
(cond [(= 0 s1) e2]
[(= 0 s2) e1]
[(< s1 s2) (sum-uneven e1 1? e2 2?)]
[(< s2 s1) (sum-uneven e2 2? e1 1?)]
[else ;; both the same length, interleave them
(define (from-nats n)
(cond [(even? n) (decode e1 (/ n 2))]
[else (decode e2 (/ (- n 1) 2))]))
(define (to-nats x)
(cond [(1? x) (* (encode e1 x) 2)]
[(2? x) (+ 1 (* (encode e2 x) 2))]
[else (error "bad term")]))
(enum (+ s1 s2) from-nats to-nats)])])
(cond [(not (xor alternate? append?))
(redex-error 'disj-sum/e "Conflicting options chosen, must pick exactly one of #:alternate? or #:append?")]
[alternate?
(cond [(= 0 s1) e2]
[(= 0 s2) e1]
[(< s1 s2) (alternate-uneven e1 1? e2 2? #:less-first? #t)]
[(< s2 s1) (alternate-uneven e2 2? e1 1? #:less-first? #f)]
[else ;; both the same length, interleave them
(define (from-nats n)
(cond [(even? n) (decode e1 (/ n 2))]
[else (decode e2 (/ (- n 1) 2))]))
(define (to-nats x)
(cond [(1? x) (* (encode e1 x) 2)]
[(2? x) (+ 1 (* (encode e2 x) 2))]
[else (redex-error 'encode "bad term")]))
(enum (+ s1 s2) from-nats to-nats)])]
[append?
(define (from-nat n)
(cond [(< n s1) (decode e1 n)]
[else (decode e2 (- n s1))]))
(define (to-nat x)
(cond [(1? x) (encode e1 x)]
[(2? x) (+ (encode e2 x) s1)]
[else (redex-error 'encode "bad term")]))
(enum (+ s1 s2) from-nat to-nat)]
[(nor alternate? append?)
(redex-error 'disj-sum/e "Must specify either #:alternate? or #:append?")])])
(car
(foldr (λ (e-p1 e-p2)
(match* (e-p1 e-p2)
@ -341,26 +342,6 @@
(cons empty/e (λ (_) #f))
(cons e-p e-ps))))
(define n*n
(enum +inf.f
(λ (n)
;; calculate the k for which (tri k) is the greatest
;; triangle number <= n
(let* ([k (floor-untri n)]
[t (tri k)]
[l (- n t)]
[m (- k l)])
(cons l m)))
(λ (ns)
(unless (pair? ns)
(error "not a list"))
(let ([l (car ns)]
[m (cdr ns)])
(+ (/ (* (+ l m) (+ l m 1))
2)
l))) ;; (n,m) -> (n+m)(n+m+1)/2 + n
))
;; cons/e : enum a, enum b -> enum (cons a b)
(define cons/e
(case-lambda
@ -375,7 +356,7 @@
(enum size
(λ (n) ;; bijection from n -> axb
(if (> n size)
(error "out of range")
(redex-error 'decode "out of range")
(call-with-values
(λ ()
(quotient/remainder n (enum-size e2)))
@ -384,7 +365,7 @@
((enum-from e2) r))))))
(λ (xs)
(unless (pair? xs)
(error "not a pair"))
(redex-error 'encode "not a pair"))
(define q (encode e1 (car xs)))
(define r (encode e2 (cdr xs)))
(+ (* (enum-size e2) q) r)))]
@ -399,7 +380,7 @@
((enum-from e2) q)))))
(λ (xs)
(unless (pair? xs)
(error "not a pair"))
(redex-error 'encode "not a pair"))
(+ ((enum-to e1) (car xs))
(* (enum-size e1)
((enum-to e2) (cdr xs))))))])]
@ -414,7 +395,7 @@
((enum-from e2) r)))))
(λ (xs)
(unless (pair? xs)
(error "not a pair"))
(redex-error 'encode "not a pair"))
(+ (* (enum-size e2)
((enum-to e1) (car xs)))
((enum-to e2) (cdr xs)))))]
@ -431,7 +412,7 @@
(λ (xs) ;; bijection from nxn -> n, inverse of previous
;; (n,m) -> (n+m)(n+m+1)/2 + n
(unless (pair? xs)
(error "not a pair"))
(redex-error 'encode "not a pair"))
(let ([l ((enum-to e1) (car xs))]
[m ((enum-to e2) (cdr xs))])
(+ (/ (* (+ l m) (+ l m 1))
@ -572,7 +553,7 @@
(λ (xs) ;; bijection from nxn -> n, inverse of previous
;; (n,m) -> (n+m)(n+m+1)/2 + n
(unless (pair? xs)
(error "not a pair"))
(redex-error 'encode "not a pair"))
(let ([l (encode e (car xs))]
[m (encode (f (car xs)) (cdr xs))])
(+ (/ (* (+ l m) (+ l m 1))
@ -697,7 +678,7 @@
(λ (xs) ;; bijection from nxn -> n, inverse of previous
;; (n,m) -> (n+m)(n+m+1)/2 + n
(unless (pair? xs)
(error "not a pair"))
(redex-error 'encode "not a pair"))
(let ([l (encode e (car xs))]
[m (encode (f (car xs)) (cdr xs))])
(+ (/ (* (+ l m) (+ l m 1))
@ -734,7 +715,7 @@
;; more utility enums
;; nats of course
(define (range/e low high)
(cond [(> low high) (error 'bad-range)]
(cond [(> low high) (redex-error 'range/e "invalid range: ~s, ~s" low high)]
[(infinite? high)
(if (infinite? low)
ints/e
@ -743,18 +724,18 @@
(+ n low))
(λ (n)
(- n low))
nats))]
nats/e))]
[(infinite? low)
(map/e
(λ (n)
(- high n))
(λ (n)
(+ high n))
nats)]
nats/e)]
[else
(map/e (λ (n) (+ n low))
(λ (n) (- n low))
(take/e nats (+ 1 (- high low))))]))
(λ (n) (- n low))
(take/e nats/e (+ 1 (- high low))))]))
;; thunk/e : Nat or +-Inf, ( -> enum a) -> enum a
(define (thunk/e s thunk)
@ -779,18 +760,21 @@
(define many/e
(case-lambda
[(e)
(fix/e (if (= 0 (size e))
0
+inf.f)
(define fix-size
(if (= 0 (size e))
0
+inf.f))
(fix/e fix-size
(λ (self)
(disj-sum/e (cons (const/e '()) null?)
(disj-sum/e #:alternate? #t
(cons (const/e '()) null?)
(cons (cons/e e self) pair?))))]
[(e n)
(list/e (build-list n (const e)))]))
;; many1/e : enum a -> enum (nonempty listof a)
(define (many1/e e)
(cons/e e (many/e e)))
(except/e (many/e e) '()))
;; list/e : listof (enum any) -> enum (listof any)
(define (list/e es)
@ -800,10 +784,10 @@
(define (nats+/e n)
(map/e (λ (k)
(+ k n))
(λ (k)
(- k n))
nats))
(+ k n))
(λ (k)
(- k n))
nats/e))
;; fail/e : exn -> enum ()
;; returns an enum that calls a thunk

View File

@ -1,5 +1,8 @@
#lang typed/racket
(require/typed "error.rkt"
[redex-error (Symbol String Any * -> Nothing)])
(provide (struct-out env)
empty-env
add-name
@ -52,12 +55,12 @@
(: t-env-name-ref : TEnv Symbol -> Pattern)
(define/match (t-env-name-ref e n)
[((t-env names _) _)
(hash-ref names n (thunk (error (format "t-env-name-ref: name not found: ~s" n))))])
(hash-ref names n (thunk (redex-error 't-env-name-ref "name not found: ~s" n)))])
(: t-env-nrep-ref : TEnv Symbol -> (Listof (Pairof TEnv Term)))
(define/match (t-env-nrep-ref nv n)
[((t-env _ nreps) n)
(hash-ref nreps n (thunk (error (format "t-env-nrep-ref: repeat not found: ~s" n))))])
(hash-ref nreps n (thunk (redex-error 't-env-nrep-ref "repeat not found: ~s" n)))])
(: env-union : Env Env -> Env)
(define/match (env-union e1 e2)
@ -71,7 +74,11 @@
(define/match (combo _ e-t1 e-t2)
[(_ (cons nv1 t1) (cons nv2 t2))
(cons (env-union nv1 nv2)
(hash-union t1 t2 (λ (t _1 _2) (error (format "2 tags should never collide, but these did: ~s, ~s with tag: ~s in envs ~s and ~s" _1 _2 t e1 e2)))))])
(hash-union t1 t2
(λ (t _1 _2)
(redex-error 'env-union
"2 tags should never collide, but these did: ~s, ~s with tag: ~s in envs ~s and ~s"
_1 _2 t e1 e2))))])
(define nreps-union
(hash-union rs1 rs2 combo))
(env names-union nreps-union)])
@ -93,5 +100,5 @@
(define v
(cond [(and v1 v2)
(combo k v1 v2)]
[else (or v1 v2 (error "absurd"))]))
[else (or v1 v2 (redex-error 'absurd ""))]))
(values k v)))

View File

@ -1,4 +1,11 @@
#lang racket/base
(provide redex-error
exn:fail:redex?
(struct-out exn:fail:redex)
unsupported
unimplemented)
(define-struct (exn:fail:redex exn:fail) ())
(define (redex-error name fmt . args)
(define suffix (apply format fmt args))
@ -7,6 +14,9 @@
(format "~a: ~a" name suffix)
suffix))
(raise (make-exn:fail:redex message (current-continuation-marks))))
(provide redex-error
exn:fail:redex?
(struct-out exn:fail:redex))
(define (unsupported pat)
(redex-error 'generate-term "#:i-th does not support ~s patterns" pat))
(define (unimplemented pat)
(redex-error 'generate-term "#:i-th does not yet support ~s patterns" pat))

View File

@ -42,7 +42,7 @@
(walk p))
(ann-pat subenv `(hide-hole ,newsub))]
[`(side-condition ,p ,c ,s)
(error 'unsupported "side condition is not supported.")]
(unsupported "side-condition")]
[`(list ,sub-pats ...)
(define ann-sub-pats
(for/list ([sub-pat (in-list sub-pats)])
@ -56,7 +56,7 @@
(ann-pat (pure-nrep n subenv tag subp)
`(repeat ,tag ,n #f))]
[`(repeat ,p ,n ,m)
(unimplemented (format "mismatch repeat (..._!_): ~s ~s" n m))]
(unimplemented "mismatch repeat")]
[_ (walk sub-pat)])))
(define list-env
(for/fold ([accenv empty-env])
@ -140,6 +140,3 @@
(define (pure-ann-pat pat)
(ann-pat empty-env pat))
(define (unimplemented pat-name)
(redex-error 'unsupported "generate-term #:i-th currently doesn't support pattern type: ~a" pat-name))

View File

@ -16,9 +16,24 @@
(unless (redex-match l p term)
(error 'bad-term (format "line ~a: i=~a" line i))))))))]))
(define-language Nats
(n natural))
(try-it 100 Nats n)
;; base types
(define-language Base
(a any)
(num number)
(s string)
(nat natural)
(i integer)
(r real)
(b boolean))
(try-it 100 Base a)
(try-it 100 Base num)
(try-it 100 Base s)
(try-it 100 Base nat)
(try-it 100 Base i)
#;
(try-it 100 Base r)
(try-it 2 Base b)
;; Repeat test
(define-language Rep

View File

@ -48,7 +48,7 @@
(test-begin
(check-exn exn:fail?
(λ ()
(decode nats -1))))
(decode nats/e -1))))
;; ints checks
(test-begin
@ -86,8 +86,8 @@
(let ([bool-or-num (sum/e bools/e
(from-list/e '(0 1 2 3)))]
[bool-or-nat (sum/e bools/e
nats)]
[nat-or-bool (sum/e nats
nats/e)]
[nat-or-bool (sum/e nats/e
bools/e)]
[odd-or-even (sum/e evens/e
odds/e)])
@ -123,21 +123,28 @@
(check-equal? (encode odd-or-even 1) 1)
(check-equal? (encode odd-or-even 2) 2)
(check-equal? (encode odd-or-even 3) 3)
(check-bijection? odd-or-even)))
(check-bijection? odd-or-even)
;; Known bug, won't fix because I'm getting rid of sum/e anyway
;; (check-bijection? nat-or-bool)
))
(test-begin
(define bool-or-num
(disj-sum/e (cons bools/e boolean?)
(disj-sum/e #:alternate? #t
(cons bools/e boolean?)
(cons (from-list/e '(0 1 2 3)) number?)))
(define bool-or-nat
(disj-sum/e (cons bools/e boolean?)
(cons nats number?)))
(disj-sum/e #:alternate? #t
(cons bools/e boolean?)
(cons nats/e number?)))
(define nat-or-bool
(disj-sum/e (cons nats number?)
(cons bools/e boolean?)))
(disj-sum/e #:alternate? #t
(cons nats/e number?)
(cons bools/e boolean?)))
(define odd-or-even
(disj-sum/e (cons evens/e even?)
(cons odds/e odd?)))
(disj-sum/e #:alternate? #t
(cons evens/e even?)
(cons odds/e odd?)))
(check-equal? (size bool-or-num) 6)
(check-equal? (decode bool-or-num 0) #t)
@ -170,15 +177,47 @@
(check-equal? (encode odd-or-even 1) 1)
(check-equal? (encode odd-or-even 2) 2)
(check-equal? (encode odd-or-even 3) 3)
(check-bijection? odd-or-even))
(check-bijection? odd-or-even)
(check-bijection? nat-or-bool))
(test-begin
(define bool-or-num
(disj-sum/e #:append? #t
(cons bools/e boolean?)
(cons (from-list/e '(0 1 2 3)) number?)))
(define bool-or-nat
(disj-sum/e #:append? #t
(cons bools/e boolean?)
(cons nats/e number?)))
(check-equal? (size bool-or-num) 6)
(check-equal? (decode bool-or-num 0) #t)
(check-equal? (decode bool-or-num 1) #f)
(check-equal? (decode bool-or-num 2) 0)
(check-equal? (decode bool-or-num 3) 1)
(check-equal? (decode bool-or-num 4) 2)
(check-equal? (decode bool-or-num 5) 3)
(check-exn exn:fail?
(λ ()
(decode bool-or-num 6)))
(check-bijection? bool-or-num)
(check-equal? (size bool-or-nat)
+inf.f)
(check-equal? (decode bool-or-nat 0) #t)
(check-equal? (decode bool-or-nat 1) #f)
(check-equal? (decode bool-or-nat 2) 0)
(check-bijection? bool-or-nat))
;; cons/e tests
(define bool*bool (cons/e bools/e bools/e))
(define 1*b (cons/e (const/e 1) bools/e))
(define b*1 (cons/e bools/e (const/e 1)))
(define bool*nats (cons/e bools/e nats))
(define nats*bool (cons/e nats bools/e))
(define nats*nats (cons/e nats nats))
(define bool*nats (cons/e bools/e nats/e))
(define nats*bool (cons/e nats/e bools/e))
(define nats*nats (cons/e nats/e nats/e))
(define ns-equal? (λ (ns ms)
(and (= (car ns)
(car ms))
@ -258,7 +297,7 @@
;; dep/e tests
(define (up-to n)
(take/e nats (+ n 1)))
(take/e nats/e (+ n 1)))
(define 3-up
(dep/e
@ -271,10 +310,10 @@
nats+/e))
(define nats-to
(dep/e nats up-to))
(dep/e nats/e up-to))
(define nats-up
(dep/e nats nats+/e))
(dep/e nats/e nats+/e))
(test-begin
(check-equal? (size 3-up) 6)
@ -336,7 +375,7 @@
up-to))
(define nats-to-2
(dep/e nats up-to))
(dep/e nats/e up-to))
(test-begin
(check-equal? (size 3-up-2) 6)
@ -384,25 +423,22 @@
'(0 1 2 3)))
;; except/e test
(define not-3 (except/e nats '(3)))
(define not-3 (except/e nats/e 3))
(test-begin
(check-equal? (decode not-3 0) 0)
(check-equal? (decode not-3 3) 4)
(check-bijection? not-3))
(define not-a (except/e nats '(a)))
(test-begin
(check-equal? (decode not-a 0) 0)
(check-bijection? not-a))
;; fold-enum tests
(define complicated
(fold-enum
(λ (excepts n)
(except/e (up-to n) excepts))
(apply except/e (up-to n) excepts))
'(2 4 6)))
(check-bijection? complicated)
;; many/e tests
(define natss
(many/e nats))
(many/e nats/e))
(check-bijection? natss)