diff --git a/lib/minikanren/intarith.sx b/lib/minikanren/intarith.sx index 7f16a36b..1ca9aee2 100644 --- a/lib/minikanren/intarith.sx +++ b/lib/minikanren/intarith.sx @@ -54,3 +54,9 @@ (project (a b) (if (and (number? a) (and (number? b) (not (= a b)))) succeed fail)))) + +(define numbero (fn (x) (project (x) (if (number? x) succeed fail)))) + +(define stringo (fn (x) (project (x) (if (string? x) succeed fail)))) + +(define symbolo (fn (x) (project (x) (if (symbol? x) succeed fail)))) diff --git a/lib/minikanren/tests/types.sx b/lib/minikanren/tests/types.sx new file mode 100644 index 00000000..5eb50e6f --- /dev/null +++ b/lib/minikanren/tests/types.sx @@ -0,0 +1,52 @@ +;; lib/minikanren/tests/types.sx — type-predicate goals. + +(mk-test + "numbero-on-int" + (run* q (numbero 5)) + (list (make-symbol "_.0"))) +(mk-test "numbero-on-string" (run* q (numbero "5")) (list)) +(mk-test "numbero-on-symbol" (run* q (numbero (quote x))) (list)) +(mk-test "numbero-on-list" (run* q (numbero (list 1))) (list)) + +(mk-test + "stringo-on-string" + (run* q (stringo "hi")) + (list (make-symbol "_.0"))) +(mk-test "stringo-on-int" (run* q (stringo 5)) (list)) +(mk-test + "stringo-on-keyword" + (run* q (stringo :k)) + (list (make-symbol "_.0"))) ;; SX keywords ARE strings + +(mk-test + "symbolo-on-symbol" + (run* q (symbolo (quote x))) + (list (make-symbol "_.0"))) +(mk-test "symbolo-on-string" (run* q (symbolo "x")) (list)) +(mk-test "symbolo-on-int" (run* q (symbolo 5)) (list)) + +;; --- combine with membero for type-filtered enumeration --- + +(mk-test + "membero-numbero-filter" + (run* + q + (fresh + (x) + (membero x (list 1 "a" 2 "b" 3)) + (numbero x) + (== q x))) + (list 1 2 3)) + +(mk-test + "membero-stringo-filter" + (run* + q + (fresh + (x) + (membero x (list 1 "a" 2 "b" 3)) + (stringo x) + (== q x))) + (list "a" "b")) + +(mk-tests-run!) diff --git a/plans/minikanren-on-sx.md b/plans/minikanren-on-sx.md index dbce01e9..d40a86c9 100644 --- a/plans/minikanren-on-sx.md +++ b/plans/minikanren-on-sx.md @@ -173,6 +173,11 @@ _(none yet)_ _Newest first._ +- **2026-05-08** — **numbero / stringo / symbolo (type predicates)**: ground-only + type tests via project. Compose with `membero` for type-filtered enumeration: + `(fresh (x) (membero x (1 "a" 2 "b" 3)) (numbero x) (== q x))` → `(1 2 3)`. + Note: SX keywords are strings, so `(stringo :k)` succeeds. 12 new tests, + 328/328 cumulative. - **2026-05-08** — **Graph reachability via patho**: classic miniKanren graph search. `edgeo` looks up edges in a fact list via `membero`; `patho` recursively builds paths via direct-edge OR (one edge + recurse + cons).