问题
Reasoned Schemer 描述了如何使用 miniKanren,它类似于 Prolog,但它是类 Lisp 语言的库。这本书的“第一诫”是这样的:
要将值为布尔值的函数转换为值为目标的函数,请将 cond 替换为 conde 并取消嵌套每个问题和答案。通过用#s(或#u)替换答案#t(或#f)来取消嵌套。
除了通过一些大致等效的示例外,它们并没有真正定义取消嵌套。最清楚的是:取消嵌套将您(list? (cdr l))
从
(fresh (d)
(cdro l d)
(listo d))
我不明白为什么需要取消嵌套。例如,对于上述目标,为什么 tp write 还不够(listo (cdr l))
?
[1] 我在 Racket 中的迷你 kanren 设置
如此处所述,我运行raco pkg install minikanren
然后定义了一些缺失的部分。
[2] 一些你可能不需要的函数定义
以下是它的定义listo
和它使用的所有内容,除了在minikanren
库或 Racket 的前奏中定义的东西。
(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)))