From e7dca2675cdbba6895377403126e19414afbc3ed Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 8 May 2026 11:13:22 +0000 Subject: [PATCH] =?UTF-8?q?mk:=20everyo=20/=20someo=20=E2=80=94=20predicat?= =?UTF-8?q?e-style=20relations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (everyo rel l): every element of l satisfies the unary relation rel. (someo rel l): some element does. Both compose with intarith and other predicate-shaped goals: (everyo (fn (x) (lto-i x 10)) (list 1 5 9)) -> succeeds (someo (fn (x) (lto-i 100 x)) (list 5 50 200)) -> succeeds 10 new tests, 310/310 cumulative. --- lib/minikanren/relations.sx | 16 ++++++ lib/minikanren/tests/predicates.sx | 87 ++++++++++++++++++++++++++++++ plans/minikanren-on-sx.md | 5 ++ 3 files changed, 108 insertions(+) create mode 100644 lib/minikanren/tests/predicates.sx diff --git a/lib/minikanren/relations.sx b/lib/minikanren/relations.sx index 6c7d6cf0..84d4e76b 100644 --- a/lib/minikanren/relations.sx +++ b/lib/minikanren/relations.sx @@ -140,3 +140,19 @@ (conde ((nullo l1) (nullo l2)) ((fresh (a d a-prime d-prime) (conso a d l1) (conso a-prime d-prime l2) (rel a a-prime) (mapo rel d d-prime)))))) + +(define + everyo + (fn + (rel l) + (conde + ((nullo l)) + ((fresh (a d) (conso a d l) (rel a) (everyo rel d)))))) + +(define + someo + (fn + (rel l) + (conde + ((fresh (a d) (conso a d l) (rel a))) + ((fresh (a d) (conso a d l) (someo rel d)))))) diff --git a/lib/minikanren/tests/predicates.sx b/lib/minikanren/tests/predicates.sx new file mode 100644 index 00000000..7242b278 --- /dev/null +++ b/lib/minikanren/tests/predicates.sx @@ -0,0 +1,87 @@ +;; lib/minikanren/tests/predicates.sx — everyo, someo. + +;; --- everyo --- + +(mk-test + "everyo-empty-trivially-true" + (run* q (everyo (fn (x) (== x 1)) (list))) + (list (make-symbol "_.0"))) + +(mk-test + "everyo-all-match" + (run* + q + (everyo + (fn (x) (== x 1)) + (list 1 1 1))) + (list (make-symbol "_.0"))) + +(mk-test + "everyo-some-mismatch" + (run* + q + (everyo + (fn (x) (== x 1)) + (list 1 2 1))) + (list)) + +(mk-test + "everyo-with-intarith" + (run* + q + (everyo + (fn (x) (lto-i x 10)) + (list 1 5 9))) + (list (make-symbol "_.0"))) + +(mk-test + "everyo-with-intarith-fail" + (run* + q + (everyo + (fn (x) (lto-i x 5)) + (list 1 5 9))) + (list)) + +;; --- someo --- + +(mk-test + "someo-finds-element" + (run* + q + (someo + (fn (x) (== x 2)) + (list 1 2 3))) + (list (make-symbol "_.0"))) + +(mk-test + "someo-not-found" + (run* + q + (someo + (fn (x) (== x 99)) + (list 1 2 3))) + (list)) + +(mk-test + "someo-empty-fails" + (run* q (someo (fn (x) (== x 1)) (list))) + (list)) + +(mk-test + "someo-multiple-matches-yields-multiple" + (let + ((res (run* q (fresh (x) (someo (fn (y) (== y x)) (list 1 2 1)) (== q x))))) + (len res)) + 3) + +(mk-test + "someo-with-intarith" + (run* + q + (someo + (fn (x) (lto-i 100 x)) + (list 5 50 200))) + (list (make-symbol "_.0"))) + +(mk-tests-run!) diff --git a/plans/minikanren-on-sx.md b/plans/minikanren-on-sx.md index 2fd26a99..cd7c3b79 100644 --- a/plans/minikanren-on-sx.md +++ b/plans/minikanren-on-sx.md @@ -173,6 +173,11 @@ _(none yet)_ _Newest first._ +- **2026-05-08** — **everyo / someo (predicate-style relations)**: + `(everyo rel l)` — every element of l satisfies rel; `(someo rel l)` — + some element does. Both compose with intarith for numeric tests: + `(everyo (fn (x) (lto-i x 10)) (list 1 5 9))` succeeds. 10 new tests, + 310/310 cumulative. - **2026-05-08** — **mapo (relational map) — 300 test milestone**: `(mapo rel l1 l2)` succeeds when l2 is l1 with each element rel-related. Works forward and backward; composes with intarith — `(mapo (fn (a b) (*o-i