;;; Code that accompanies ``The Reasoned Schemer'' ;;; Daniel P. Friedman, William E. Byrd and Oleg Kiselyov ;;; MIT Press, Cambridge, MA, 2005 ;;; ;;; The implementation of the logic system used in the book ;;; This file was generated by writeminikanren.pl ;;; Generated at 2005-08-12 11:27:16 ;;; Adapted for Chicken by Alex Shinn 2005-11-02 10:14:45 (module mini-kanren * (import scheme chicken) (include "mini-kanren.scm") (define rhs cdr) (define lhs car) (define size-s length) (define var vector) (define var? vector?) (define empty-s '()) (define walk (lambda (v s) (cond ((var? v) (cond ((assq v s) => (lambda (a) (walk (rhs a) s))) (else v))) (else v)))) (define ext-s (lambda (x v s) (cons `(,x . ,v) s))) (define unify (lambda (v w s) (let ((v (walk v s)) (w (walk w s))) (cond ((eq? v w) s) ((var? v) (ext-s v w s)) ((var? w) (ext-s w v s)) ((and (pair? v) (pair? w)) (cond ((unify (car v) (car w) s) => (lambda (s) (unify (cdr v) (cdr w) s))) (else #f))) ((equal? v w) s) (else #f))))) (define ext-s-check (lambda (x v s) (cond ((occurs-check x v s) #f) (else (ext-s x v s))))) (define occurs-check (lambda (x v s) (let ((v (walk v s))) (cond ((var? v) (eq? v x)) ((pair? v) (or (occurs-check x (car v) s) (occurs-check x (cdr v) s))) (else #f))))) (define unify-check (lambda (v w s) (let ((v (walk v s)) (w (walk w s))) (cond ((eq? v w) s) ((var? v) (ext-s-check v w s)) ((var? w) (ext-s-check w v s)) ((and (pair? v) (pair? w)) (cond ((unify-check (car v) (car w) s) => (lambda (s) (unify-check (cdr v) (cdr w) s))) (else #f))) ((equal? v w) s) (else #f))))) (define walk* (lambda (v s) (let ((v (walk v s))) (cond ((var? v) v) ((pair? v) (cons (walk* (car v) s) (walk* (cdr v) s))) (else v))))) (define reify-s (lambda (v s) (let ((v (walk v s))) (cond ((var? v) (ext-s v (reify-name (size-s s)) s)) ((pair? v) (reify-s (cdr v) (reify-s (car v) s))) (else s))))) (define reify-name (lambda (n) (string->symbol (string-append "_" "." (number->string n))))) (define reify (lambda (v) (walk* v (reify-s v empty-s)))) (define map-inf (lambda (n p a-inf) (case-inf a-inf '() ((a) (cons (p a) '())) ((a f) (cons (p a) (cond ((not n) (map-inf n p (f))) ((> n 1) (map-inf (- n 1) p (f))) (else '()))))))) (define succeed (lambdag@ (s) (unit s))) (define fail (lambdag@ (s) (mzero))) (define == (lambda (v w) (lambdag@ (s) (cond ((unify v w s) => succeed) (else (fail s)))))) (define ==-check (lambda (v w) (lambdag@ (s) (cond ((unify-check v w s) => succeed) (else (fail s)))))) (define mplus (lambda (a-inf f) (case-inf a-inf (f) ((a) (choice a f)) ((a f0) (choice a (lambdaf@ () (mplus (f0) f))))))) (define bind (lambda (a-inf g) (case-inf a-inf (mzero) ((a) (g a)) ((a f) (mplus (g a) (lambdaf@ () (bind (f) g))))))) (define mplusi (lambda (a-inf f) (case-inf a-inf (f) ((a) (choice a f)) ((a f0) (choice a (lambdaf@ () (mplusi (f) f0))))))) (define bindi (lambda (a-inf g) (case-inf a-inf (mzero) ((a) (g a)) ((a f) (mplusi (g a) (lambdaf@ () (bindi (f) g))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Extra forms appearing in the framenotes of the book. ;;; ;;; run* is a convenient macro (see frame 10 on page 4 of chapter 1) ;;; (run* (q) ...) is identical to (run #f (q) ...) ;;; See frame 40 on page 68 of chapter 5 for a description of 'lambda-limited'. ;;; See frame 47 on page 138 of chapter 9 for a description of 'project'. (define ll (lambda (n x g) (lambdag@ (s) (let ((v (walk x s))) (cond ((var? v) (g (ext-s x 1 s))) ((< v n) (g (ext-s x (+ v 1) s))) (else (fail s))))))) ;;; Useful definitions from the book (define caro (lambda (p a) (fresh (d) (== (cons a d) p)))) (define cdro (lambda (p d) (fresh (a) (== (cons a d) p)))) (define conso (lambda (a d p) (== (cons a d) p))) (define nullo (lambda (x) (== '() x))) (define eqo (lambda (x y) (== x y))) (define eq-caro (lambda (l x) (caro l x))) (define pairo (lambda (p) (fresh (a d) (conso a d p)))) (define listo (lambda (l) (conde ((nullo l) succeed) ((pairo l) (fresh (d) (cdro l d) (listo d))) (else fail)))) (define membero (lambda (x l) (conde ((nullo l) fail) ((eq-caro l x) succeed) (else (fresh (d) (cdro l d) (membero x d)))))) (define rembero (lambda (x l out) (conde ((nullo l) (== '() out)) ((eq-caro l x) (cdro l out)) (else (fresh (a d res) (conso a d l) (rembero x d res) (conso a res out)))))) (define appendo (lambda (l s out) (conde ((nullo l) (== s out)) (else (fresh (a d res) (conso a d l) (conso a res out) (appendo d s res)))))) (define anyo (lambda (g) (conde (g succeed) (else (anyo g))))) (define nevero (anyo fail)) (define alwayso (anyo succeed)) (define build-num (lambda (n) (cond ((zero? n) '()) ((and (not (zero? n)) (even? n)) (cons 0 (build-num (quotient n 2)))) ((odd? n) (cons 1 (build-num (quotient (- n 1) 2))))))) (define full-addero (lambda (b x y r c) (conde ((== 0 b) (== 0 x) (== 0 y) (== 0 r) (== 0 c)) ((== 1 b) (== 0 x) (== 0 y) (== 1 r) (== 0 c)) ((== 0 b) (== 1 x) (== 0 y) (== 1 r) (== 0 c)) ((== 1 b) (== 1 x) (== 0 y) (== 0 r) (== 1 c)) ((== 0 b) (== 0 x) (== 1 y) (== 1 r) (== 0 c)) ((== 1 b) (== 0 x) (== 1 y) (== 0 r) (== 1 c)) ((== 0 b) (== 1 x) (== 1 y) (== 0 r) (== 1 c)) ((== 1 b) (== 1 x) (== 1 y) (== 1 r) (== 1 c)) (else fail)))) (define poso (lambda (n) (fresh (a d) (== `(,a . ,d) n)))) (define >1o (lambda (n) (fresh (a ad dd) (== `(,a ,ad . ,dd) n)))) (define addero (lambda (d n m r) (condi ((== 0 d) (== '() m) (== n r)) ((== 0 d) (== '() n) (== m r) (poso m)) ((== 1 d) (== '() m) (addero 0 n '(1) r)) ((== 1 d) (== '() n) (poso m) (addero 0 '(1) m r)) ((== '(1) n) (== '(1) m) (fresh (a c) (== `(,a ,c) r) (full-addero d 1 1 a c))) ((== '(1) n) (gen-addero d n m r)) ((== '(1) m) (>1o n) (>1o r) (addero d '(1) n r)) ((>1o n) (gen-addero d n m r)) (else fail)))) (define gen-addero (lambda (d n m r) (fresh (a b c e x y z) (== `(,a . ,x) n) (== `(,b . ,y) m) (poso y) (== `(,c . ,z) r) (poso z) (alli (full-addero d a b c e) (addero e x y z))))) (define +o (lambda (n m k) (addero 0 n m k))) (define -o (lambda (n m k) (+o m k n))) (define *o (lambda (n m p) (condi ((== '() n) (== '() p)) ((poso n) (== '() m) (== '() p)) ((== '(1) n) (poso m) (== m p)) ((>1o n) (== '(1) m) (== n p)) ((fresh (x z) (== `(0 . ,x) n) (poso x) (== `(0 . ,z) p) (poso z) (>1o m) (*o x m z))) ((fresh (x y) (== `(1 . ,x) n) (poso x) (== `(0 . ,y) m) (poso y) (*o m n p))) ((fresh (x y) (== `(1 . ,x) n) (poso x) (== `(1 . ,y) m) (poso y) (odd-*o x n m p))) (else fail)))) (define odd-*o (lambda (x n m p) (fresh (q) (bound-*o q p n m) (*o x m q) (+o `(0 . ,q) m p)))) (define bound-*o (lambda (q p n m) (conde ((nullo q) (pairo p)) (else (fresh (x y z) (cdro q x) (cdro p y) (condi ((nullo n) (cdro m z) (bound-*o x y z '())) (else (cdro n z) (bound-*o x y z m)))))))) (define =lo (lambda (n m) (conde ((== '() n) (== '() m)) ((== '(1) n) (== '(1) m)) (else (fresh (a x b y) (== `(,a . ,x) n) (poso x) (== `(,b . ,y) m) (poso y) (=lo x y)))))) (define 1o m)) (else (fresh (a x b y) (== `(,a . ,x) n) (poso x) (== `(,b . ,y) m) (poso y) (1o b) (=lo n b) (+o r b n)) ((== '(1) b) (poso q) (+o r '(1) n)) ((== '() b) (poso q) (== r n)) ((== '(0 1) b) (fresh (a ad dd) (poso dd) (== `(,a ,ad . ,dd) n) (exp2 n '() q) (fresh (s) (splito n dd r s)))) ((fresh (a ad add ddd) (conde ((== '(1 1) b)) (else (== `(,a ,ad ,add . ,ddd) b)))) (1o n) (== '(1) q) (fresh (s) (splito n b s '(1)))) ((fresh (q1 b2) (alli (== `(0 . ,q1) q) (poso q1) (1o q) (fresh (q1 nq1) (+o q1 '(1) q) (repeated-mul n q1 nq1) (*o nq1 n nq))) (else fail)))) (define expo (lambda (b q n) (logo n b q '()))) )