;; lib/minikanren/nafc.sx — Phase 5 piece C: negation as finite failure.
;;
;;   (nafc g)
;;     succeeds (yields the input substitution) if g has zero answers
;;     against that substitution; fails (mzero) if g has at least one.
;;
;; Caveat: `nafc` is unsound under the open-world assumption. It only
;; makes sense for goals over fully-ground terms, or with the explicit
;; understanding that adding more facts could flip the answer. Use
;; `(project (...) ...)` to ensure the relevant vars are ground first.
;;
;; Caveat 2: stream-take forces g for at least one answer; if g is
;; infinitely-ground (say, a divergent search over an unbound list),
;; nafc itself will diverge. Standard miniKanren limitation.

(define
  nafc
  (fn
    (g)
    (fn
      (s)
      (let
        ((peek (stream-take 1 (g s))))
        (if (empty? peek) (unit s) mzero)))))
