From 4d861575df8842b82ad152095575a07760f84194 Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 8 May 2026 11:47:27 +0000 Subject: [PATCH] =?UTF-8?q?mk:=20selecto=20=E2=80=94=20choose=20element=20?= =?UTF-8?q?+=20rest=20of=20list?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Classic miniKanren relation. (selecto x rest l) holds when l contains x at any position with `rest` being everything else. Direct base case (l = (x . rest)) plus the skip-head recursion that threads the head through to the result rest. Run modes: enumerate every (x, rest) split; recover rest given an element; recover an element given the rest; (and ground/all combinations). 6 new tests, 411/411 cumulative. --- lib/minikanren/relations.sx | 8 ++++++ lib/minikanren/tests/selecto.sx | 46 +++++++++++++++++++++++++++++++++ plans/minikanren-on-sx.md | 1 + 3 files changed, 55 insertions(+) create mode 100644 lib/minikanren/tests/selecto.sx diff --git a/lib/minikanren/relations.sx b/lib/minikanren/relations.sx index 4b9c61c2..b2b837a8 100644 --- a/lib/minikanren/relations.sx +++ b/lib/minikanren/relations.sx @@ -82,6 +82,14 @@ (appendo front-and-s back l) (appendo front s front-and-s)))) +(define + selecto + (fn + (x rest l) + (conde + ((conso x rest l)) + ((fresh (a d r) (conso a d l) (conso a r rest) (selecto x r d)))))) + (define lengtho (fn diff --git a/lib/minikanren/tests/selecto.sx b/lib/minikanren/tests/selecto.sx new file mode 100644 index 00000000..ba34a86b --- /dev/null +++ b/lib/minikanren/tests/selecto.sx @@ -0,0 +1,46 @@ +;; lib/minikanren/tests/selecto.sx — choose an element + rest of list. + +(mk-test + "selecto-enumerate" + (run* + q + (fresh + (x r) + (selecto x r (list 1 2 3)) + (== q (list x r)))) + (list + (list 1 (list 2 3)) + (list 2 (list 1 3)) + (list 3 (list 1 2)))) + +(mk-test + "selecto-find-rest" + (run* q (selecto 2 q (list 1 2 3))) + (list (list 1 3))) + +(mk-test + "selecto-find-element" + (run* + q + (selecto + q + (list 1 3) + (list 1 2 3))) + (list 2)) + +(mk-test + "selecto-element-not-present-fails" + (run* q (selecto 99 q (list 1 2 3))) + (list)) + +(mk-test + "selecto-empty-list-fails" + (run* q (selecto q (list) (list))) + (list)) + +(mk-test + "selecto-singleton" + (run* q (fresh (x r) (selecto x r (list :only)) (== q (list x r)))) + (list (list :only (list)))) + +(mk-tests-run!) diff --git a/plans/minikanren-on-sx.md b/plans/minikanren-on-sx.md index b2dcaa2e..b040fb45 100644 --- a/plans/minikanren-on-sx.md +++ b/plans/minikanren-on-sx.md @@ -173,6 +173,7 @@ _(none yet)_ _Newest first._ +- **2026-05-08** — **selecto**: classic miniKanren "choose an element + rest". Direct base (l = (x . rest)) plus skip-head recurse. Enumerates all (element, rest) splits in run*; runs forward, backward, mid-pipeline. 6 new tests, 411/411 cumulative. - **2026-05-08** — **subo (contiguous sublist)**: Two appendos chained — l = front ++ s ++ back. Goal order matters: appendo on the ground l first, so the search is finitary; then constrain front. 7 new tests, 405/405 cumulative. - **2026-05-08** — **prefixo + suffixo**: classic appendo-derived sublist relations. (prefixo p l) ≡ p ⊕ ? = l; (suffixo s l) ≡ ? ⊕ s = l. Both enumerate all prefixes/suffixes when given a fresh first arg. 9 new tests, 398/398 cumulative. - **2026-05-08** — **palindromeo**: 2-line definition (reverseo + ==). Succeeds when a list reads the same forwards and backwards. 7 new tests, 389/389 cumulative.