diff --git a/lib/minikanren/relations.sx b/lib/minikanren/relations.sx index b04768d7..2475125a 100644 --- a/lib/minikanren/relations.sx +++ b/lib/minikanren/relations.sx @@ -66,6 +66,8 @@ ((nullo l) (nullo r)) ((fresh (a d res-rev) (conso a d l) (reverseo d res-rev) (appendo res-rev (list a) r)))))) +(define palindromeo (fn (l) (fresh (rev) (reverseo l rev) (== l rev)))) + (define lengtho (fn @@ -82,6 +84,7 @@ ((conso a l p)) ((fresh (h t pt) (conso h t l) (conso h pt p) (inserto a t pt)))))) + (define permuteo (fn @@ -90,7 +93,6 @@ ((nullo l) (nullo p)) ((fresh (a d perm-d) (conso a d l) (permuteo d perm-d) (inserto a perm-d p)))))) - (define flatteno (fn diff --git a/lib/minikanren/tests/palindromeo.sx b/lib/minikanren/tests/palindromeo.sx new file mode 100644 index 00000000..0d28773f --- /dev/null +++ b/lib/minikanren/tests/palindromeo.sx @@ -0,0 +1,44 @@ +;; lib/minikanren/tests/palindromeo.sx — palindromic list relation. + +(mk-test + "palindromeo-empty" + (run* q (palindromeo (list))) + (list (make-symbol "_.0"))) + +(mk-test + "palindromeo-singleton" + (run* q (palindromeo (list :a))) + (list (make-symbol "_.0"))) + +(mk-test + "palindromeo-pair-equal" + (run* q (palindromeo (list 1 1))) + (list (make-symbol "_.0"))) + +(mk-test + "palindromeo-pair-unequal-fails" + (run* q (palindromeo (list 1 2))) + (list)) + +(mk-test + "palindromeo-five-yes" + (run* + q + (palindromeo + (list 1 2 3 2 1))) + (list (make-symbol "_.0"))) + +(mk-test + "palindromeo-five-no" + (run* + q + (palindromeo + (list 1 2 3 4 5))) + (list)) + +(mk-test + "palindromeo-strings" + (run* q (palindromeo (list "a" "b" "a"))) + (list (make-symbol "_.0"))) + +(mk-tests-run!) diff --git a/plans/minikanren-on-sx.md b/plans/minikanren-on-sx.md index 733eaea6..cb59ed9b 100644 --- a/plans/minikanren-on-sx.md +++ b/plans/minikanren-on-sx.md @@ -173,6 +173,7 @@ _(none yet)_ _Newest first._ +- **2026-05-08** — **palindromeo**: 2-line definition (reverseo + ==). Succeeds when a list reads the same forwards and backwards. 7 new tests, 389/389 cumulative. - **2026-05-08** — **not-membero**: relational "x is not a member of l". Uses `nafc + ==` per element (the same skeleton all-distincto uses). Useful as a constraint-style filter: `(membero x dom) (not-membero x