t3x.org / nss / amk.html

(Nils' Scheme Snippets)

 
Paren matching: ON  |  Category: logic  |  Overview  |  Scheme Books  |  License
 

(run* (symbol) query) => list

 
Purpose
Another Mirco Kanren - embed logic programming into Scheme. Run the given AMK query and return its result, if any. See the book Logic Progamming in Scheme for an introduction to AMK.
 
Arguments
symbol variable binding the result (optional)
query AMK program
 
Example
(run* (vq) (appendo vq (_) '(a b c))) 
=> (() (a) (a b) (a b c))
; ----- core -----

(define (fail x) '())

(define (succeed x) (list x))

(define failed? null?)

(define (var x) (cons '? x))

(define (var? x)
  (and (pair? x)
       (eq? (car x) '?)))

(define empty-s '())

(define _bottom_ (var 'bottom))

(define (atom? x) (not (pair? x)))

(define (ext-s x v s) (cons (cons x v) s))

(define (walk x s)
  (if (not (var? x))
      x
      (let ((v (assq x s)))
        (if v
            (walk (cdr v) s)
            x))))

(define (unify x y s)
  (let ((x (walk x s))
        (y (walk y s)))
    (cond
      ((eqv? x y) s)
      ((var? x) (ext-s x y s))
      ((var? y) (ext-s y x s))
      ((or (atom? x) (atom? y)) #f)
      (else (let ((s (unify (car x) (car y) s)))
              (and s (unify (cdr x) (cdr y) s)))))))

(define (== x y)
  (lambda (s)
    (let ((s2 (unify x y s)))
      (if s2
          (succeed s2)
          (fail s)))))

(define (any* . g*)
  (lambda (s)
    (letrec
      ((try
         (lambda g*
           (if (null? g*)
               (fail s)
               (append ((car g*) s)
                       (apply try (cdr g*)))))))
      (apply try g*))))

(define-syntax any
  (syntax-rules ()
    ((_) fail)
    ((_ g ...)
       (any* (lambda (s) (g s)) ...))))

(define (all . gs)
  (lambda (s)
    (letrec
      ((try
         (lambda (gs subs)
           (if (null? gs)
               subs
               (try (cdr gs)
                    (apply append
                           (map (car gs) subs)))))))
      (try gs (succeed s)))))

(define (one* . gs)
  (lambda (s)
    (letrec
      ((try
         (lambda gs
           (if (null? gs)
               (fail s)
               (let ((out ((car gs) s)))
                 (if (failed? out)
                     (apply try (cdr gs))
                     out))))))
      (apply try gs))))

(define-syntax one
  (syntax-rules ()
    ((_) fail)
    ((_ g ...)
       (one* (lambda (s) (g s)) ...))))

(define (neg g)
  (lambda (s)
    (let ((out (g s)))
      (if (failed? out)
          (succeed s)
          (fail s)))))

(define-syntax fresh
  (syntax-rules ()
    ((_ () g)
       (let () g))
    ((_ (v ...) g)
       (let ((v (var 'v)) ...) g))))

(define (occurs? x y s)
  (let ((v (walk y s)))
    (cond
      ((var? y) (eq? x y))
      ((var? v) (eq? x v))
      ((atom? v) #f)
      (else (or (occurs? x (car v) s)
                (occurs? x (cdr v) s))))))

(define (circular? x s)
  (let ((v (walk x s)))
    (if (eq? x v)
        #f
        (occurs? x (walk x s) s))))

(define (walk* x s)
  (letrec
    ((w*
       (lambda (x s)
         (let ((x (walk x s)))
           (cond
             ((var? x) x)
             ((atom? x) x)
             (else (cons (w* (car x) s)
                         (w* (cdr x) s))))))))
    (cond
      ((circular? x s) _bottom_)
      ((eq? x (walk x s)) empty-s)
      (else (w* x s)))))

(define (preserve-bottom s)
  (if (occurs? _bottom_ s s)
      '()
      s))

(define (reify-name n)
  (string->symbol
    (string-append "_." (number->string n))))

(define (reify v)
  (letrec
    ((reify-s
       (lambda (v s)
         (let ((v (walk v s)))
           (cond
             ((var? v)
               (ext-s v (reify-name (length s)) s))
             ((atom? v) s)
             (else (reify-s (cdr v)
                            (reify-s (car v) s))))))))
    (reify-s v empty-s)))

(define (_) (var '_))

(define (run x g)
  (preserve-bottom
    (map (lambda (s)
           (walk* x (append s (reify (walk* x s)))))
         (g empty-s))))

(define-syntax run*
  (syntax-rules ()
    ((_ () goal) (run #f goal))
    ((_ (v) goal) (run v goal))))

; ----- tools -----

(define vp (var 'p))
(define vq (var 'q))
(define vr (var 'r))

(define (conso a d p) (== (cons a d) p))

(define (caro p a) (conso a (_) p))

(define (cdro p d) (conso (_) d p))

(define (pairo p) (conso (_) (_) p))

(define (eqo x y) (== x y))

(define (nullo a) (eqo a '()))

(define (memo x l)
  (fresh (a d)
    (any (all (caro l a)
              (eqo x a))
         (all (cdro l d)
              (memo x d)))))

(define (appendo x y r)
  (any (all (== x '())
            (== y r))
       (fresh (vh vt va)
         (all (conso vh vt x)
              (conso vh va r)
              (appendo vt y va)))))

(define (membero x l r)
  (fresh (a d)
    (any (all (caro l a)
              (eqo x a) 
              (== r l))
         (all (cdro l d)
              (membero x d r)))))

Copyright (C) 2007 Nils M Holm <nmh @ t3x . org>