Multiple Fixed-Point Combinators

Hi, Racket Discourse.

I have been looking at the bruijn language lately because it has such a nice syntax. I'd encourage any curious readers to take a look, the author is doing some interesting things.

In any case, in a blog post, Marvin speaks about variadic fixed-point combinators, and mentions the paper, A Variadic Extension of Curry's Fixed-Point Combinator, which presents a Scheme implementation of the concept.

It's an easy read, and the code itself is largely self explanatory.

I found it immensely satisfying to write a syntax-parse-rule to explicitly create mutually recursive procedures, but the paper presents a neat functional approach, as well.

#lang racket/base

(require
  (for-syntax
   racket/base)
  syntax/parse/define)

;; explicitly construct mutually recursive procedures
(define-syntax-parse-rule (expl-fps fs ...)
  #:with (xs ...) (generate-temporaries #'(fs ...))
  #:with (fi ...) #'(fs ...) ; used for clarity, not necessary
  #:with (xi ...) #'(xs ...) ;
  (values
   ((lambda (xs ...) (fi (lambda args (apply (xi xs ...) args)) ...))
    (lambda (xs ...) (fs (lambda args (apply (xi xs ...) args)) ...))
    ...)
   ...))

(define (((curry-args xs) xi) . args)
  (apply (apply xi xs) args))

(define ((curry-xs fi) . xs)
  (apply fi (map (curry-args xs) xs)))

(define ((curry-xi xs) xi)
  (apply xi xs))

;; implicitly construct mutually recursive procedures
(define (impl-fps . fs)
  (let ([xs (map curry-xs fs)])
    (apply values (map (curry-xi xs) xs))))

(define _even? ;; partially recursive even?
  (lambda (even? odd?)
    (lambda (n)
      (if (zero? n) #t
          (odd? (- n 1))))))

(define _odd? ;; partially recursive odd?
  (lambda (even? odd?)
    (lambda (n)
      (if (zero? n) #f
          (even? (- n 1))))))

(define-values (even?₁ odd?₁) (expl-fps _even? _odd?))
(define-values (even?₂ odd?₂) (impl-fps _even? _odd?))

(even?₁ 8) ;=> #t
(odd?₁  9) ;=> #t
(even?₂ 4) ;=> #t
(odd?₂  5) ;=> #t

Happy hacking!