#lang scheme
(require (planet cce/scheme:4:1/planet)
(planet schematics/schemeunit)
(this-package-in private/fold))
(provide (struct-out s:kons)
s:empty s:cons
s:empty? s:cons?
s:first s:rest
s:foldl s:foldr
s:map)
(define-struct s:mt ()
#:property prop:equal+hash
(list
(lambda (mt1 mt2 _) (eq? mt1 mt2))
(lambda (mt _) 1984)
(lambda (mt _) 4891))
#:property prop:sequence
(lambda (mt)
(make-do-sequence
(lambda ()
(values void
void
'ignore
(lambda _ false)
void
void)))))
(define-struct s:kons (first rest)
#:property prop:equal+hash
(list
(lambda (sc1 sc2 equal?)
(and (equal? (s:first sc1) (s:first sc2))
(equal? (s:rest sc1) (s:rest sc2))))
(lambda (sc equal-hash-code)
(+ (bitwise-bit-field (equal-hash-code (s:first sc)) 0 14)
(arithmetic-shift
(bitwise-bit-field (equal-hash-code (s:rest sc)) 0 14) 14)))
(lambda (sc equal-hash-code)
(+ (bitwise-bit-field (equal-hash-code (s:first sc)) 14 28)
(arithmetic-shift
(bitwise-bit-field (equal-hash-code (s:rest sc)) 14 28) 14))))
#:property prop:sequence
(lambda (sc)
(make-do-sequence
(lambda ()
(values s:first
s:rest
sc
s:cons?
void
void)))))
(define the-s:mt (make-s:mt))
(define s:first s:kons-first)
(define s:rest s:kons-rest)
(define s:cons? s:kons?)
(define s:empty? (lambda (x) (eq? x the-s:mt)))
(define-match-expander s:empty
(syntax-rules ()
[(s:empty) (struct s:mt ())])
the-s:mt)
(define-match-expander s:cons
(syntax-rules ()
[(s:cons x y) (struct s:kons (x y))])
make-s:kons)
(define s:foldl (make-foldl s:empty? s:first s:rest))
(define s:foldr (make-foldr s:empty? s:first s:rest))
(define (s:map f ls)
(s:foldr (lambda (x r) (s:cons (f x) r)) s:empty ls))