(module combinators mzscheme
(require (lib "etc.ss")
(lib "list.ss"))
(provide curry
yrruc
constant
compose/apply
map2
map/values
fold/values
negate
conjoin
disjoin)
(define (curry f . args)
(lambda rest
(apply f (append args rest))))
(define (yrruc f . rest)
(lambda args
(apply f (append args rest))))
(define (constant v)
(lambda args v))
(define (compose/apply first . rest)
(foldl
(lambda (f accum)
(lambda args (apply accum (apply f args))))
first
rest))
(define (fold/values f inits . ls)
(recur loop ([ls ls]
[results inits])
(if (ormap null? ls)
(apply values results)
(loop (map cdr ls)
(call-with-values (lambda ()
(apply f (append (map car ls) results)))
list)))))
(define (map/values n f l-first . l-rest)
(let* ([ls (cons l-first l-rest)]
[lengths (map length ls)])
(unless (or (null? l-rest) (apply = lengths))
(raise (make-exn:fail:contract
(format
"map/values: all lists must be of same length, got lengths ~v"
lengths)
(current-continuation-marks))))
(recur loop ([ls ls])
(cond
[(ormap null? ls) (apply values (build-list n (constant null)))]
[else
(call-with-values (lambda () (apply f (map car ls)))
(lambda heads
(call-with-values (lambda () (loop (map cdr ls)))
(lambda tails
(apply values (map cons heads tails))))))]))))
(define (map2 f l-first . l-rest)
(apply map/values 2 f l-first l-rest))
(define (negate pred)
(lambda args (not (apply pred args))))
(define (conjoin . preds)
(lambda args (andmap (lambda (pred) (apply pred args)) preds)))
(define (disjoin . preds)
(lambda args (ormap (lambda (pred) (apply pred args)) preds)))
)