;; lib/minikanren/relations.sx — Phase 4 standard relations. ;; ;; Programs use native SX lists as data. Relations decompose lists via the ;; tagged cons-cell shape `(:cons h t)` because SX has no improper pairs; ;; the unifier treats `(:cons h t)` and the native list `(h . t)` as ;; equivalent, and `mk-walk*` flattens cons cells back to flat lists for ;; reification. ;; --- pair / list shape relations --- (define nullo (fn (l) (== l (list)))) (define pairo (fn (p) (fresh (a d) (== p (mk-cons a d))))) (define caro (fn (p a) (fresh (d) (== p (mk-cons a d))))) (define cdro (fn (p d) (fresh (a) (== p (mk-cons a d))))) (define conso (fn (a d p) (== p (mk-cons a d)))) (define firsto caro) (define resto cdro) (define listo (fn (l) (conde ((nullo l)) ((fresh (a d) (conso a d l) (listo d)))))) ;; --- appendo: the canary --- ;; ;; (appendo l s ls) — `ls` is the concatenation of `l` and `s`. ;; Runs forwards (l, s known → ls), backwards (ls known → all (l, s) pairs), ;; and bidirectionally (mix of bound + unbound). (define appendo (fn (l s ls) (conde ((nullo l) (== s ls)) ((fresh (a d res) (conso a d l) (conso a res ls) (appendo d s res)))))) ;; --- membero --- ;; (membero x l) — x appears (at least once) in l. (define membero (fn (x l) (conde ((fresh (d) (conso x d l))) ((fresh (a d) (conso a d l) (membero x d)))))) (define reverseo (fn (l r) (conde ((nullo l) (nullo r)) ((fresh (a d res-rev) (conso a d l) (reverseo d res-rev) (appendo res-rev (list a) r)))))) (define lengtho (fn (l n) (conde ((nullo l) (== n :z)) ((fresh (a d n-1) (conso a d l) (== n (list :s n-1)) (lengtho d n-1)))))) (define inserto (fn (a l p) (conde ((conso a l p)) ((fresh (h t pt) (conso h t l) (conso h pt p) (inserto a t pt)))))) (define permuteo (fn (l p) (conde ((nullo l) (nullo p)) ((fresh (a d perm-d) (conso a d l) (permuteo d perm-d) (inserto a perm-d p))))))