The question
The Reasoned Schemer describes how to use miniKanren, which resembles Prolog but is a library for Lisp-like languages. The book's "First Commandment" is this:
To transform a function whose value is a Boolean into a function whose value is a goal, replace cond with conde and unnest each question and answer. Unnest the answer #t (or #f) by replacing it with #s (or #u).
They don't really define unnesting, except through a few roughly equivalent example. The clearest is this: unnesting takes you from (list? (cdr l)) to
(fresh (d)
(cdro l d)
(listo d))
I don't understand why unnesting is needed. For instance, for the above goal, why is it not sufficient tp write (listo (cdr l))?
[1] My mini-kanren setup in Racket
As described here, I ran raco pkg install minikanren and then defined a few missing pieces.
[2] Some function definitions you may not need
Here are the definitions of listo and everything it uses it, except for things defined in the minikanren library or in Racket's prelude.
(define listo
(lambda (l)
(conde
((nullo l) #s)
((pairo l)
(fresh (d)
(cdro l d)
(listo d)))
(else #u))))
(define nullo
(lambda (x)
(== x '())))
(define pairo
(lambda (p)
(fresh (a d)
(conso a d p))))
(define cdro
(lambda (p d)
(fresh (a)
(== (cons a d) p))))
(define conso
(lambda (head tail result)
(== (cons head tail) result)))
the term
un-nestingmeans to modify the hierarchy of the structure - or to remove brackets.just found the book The Reasoned Schemer and the associated GitHub page, which also defines it: