我目前正在通过 The Reasoned Schemer 和 Racket 学习 miniKanren。
我有三个版本的 minikanren 实现:
The Reasoned Schemer,第一版(麻省理工学院出版社,2005 年)。我叫它
TRS1
https://github.com/miniKanren/TheReasonedSchemer
PS。它说它
condi
已被conde
执行交织的改进版本所取代。The Reasoned Schemer,第二版(麻省理工学院出版社,2018 年)。我叫它
TRS2
https://github.com/TheReasonedSchemer2ndEd/CodeFromTheReasonedSchemer2ndEd
The Reasoned Schemer,第一版(麻省理工学院出版社,2005 年)。我叫它
TRS1*
我对上面的三种实现做了一些实验:
第一个实验:
TRS1
(run* (r)
(fresh (x y)
(conde
((== 'a x) (conde
((== 'c y) )
((== 'd y))))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c) (a d) (b e) (b f))
TRS2
(run* (x y)
(conde
((== 'a x) (conde
((== 'c y) )
((== 'd y))))
((== 'b x) (conde
((== 'e y) )
((== 'f y))))))
;; => '((a c) (a d) (b e) (b f))
TRS1*
(run* (r)
(fresh (x y)
(conde
((== 'a x) (conde
((== 'c y) )
((== 'd y))))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c) (b e) (a d) (b f))
请注意,在第一个实验中,TRS1
产生TRS2
了相同的结果,但TRS1*
产生了不同的结果。
似乎conde
在TRS1
和TRS2
使用相同的搜索算法,但TRS1*
使用不同的算法。
实验二:
TRS1
(define listo
(lambda (l)
(conde
((nullo l) succeed)
((pairo l)
(fresh (d)
(cdro l d)
(listo d)))
(else fail))))
(define lolo
(lambda (l)
(conde
((nullo l) succeed)
((fresh (a)
(caro l a)
(listo a))
(fresh (d)
(cdro l d)
(lolo d)))
(else fail))))
(run 5 (x)
(lolo x))
;; => '(() (()) (() ()) (() () ()) (() () () ()))
TRS2
(defrel (listo l)
(conde
((nullo l))
((fresh (d)
(cdro l d)
(listo d)))))
(defrel (lolo l)
(conde
((nullo l))
((fresh (a)
(caro l a)
(listo a))
(fresh (d)
(cdro l d)
(lolo d)))))
(run 5 x
(lolo x))
;; => '(() (()) ((_0)) (() ()) ((_0 _1)))
TRS1*
(define listo
(lambda (l)
(conde
((nullo l) succeed)
((pairo l)
(fresh (d)
(cdro l d)
(listo d)))
(else fail))))
(define lolo
(lambda (l)
(conde
((nullo l) succeed)
((fresh (a)
(caro l a)
(listo a))
(fresh (d)
(cdro l d)
(lolo d)))
(else fail))))
(run 5 (x)
(lolo x))
;; => '(() (()) ((_.0)) (() ()) ((_.0 _.1)))
请注意,在第二个实验中,TRS2
产生TRS1*
了相同的结果,但TRS1
产生了不同的结果。
似乎conde inTRS2
和TRS1*
使用相同的搜索算法,但是TRS1
使用了不同的算法。
这些让我很困惑。
有人可以帮我在上面的每个 minikanren 实现中澄清这些不同的搜索算法吗?
很感谢。
---- 添加一个新的实验 ----
第三次实验:
TRS1
(define (tmp-rel y)
(conde
((== 'c y) )
((tmp-rel-2 y))))
(define (tmp-rel-2 y)
(== 'd y)
(tmp-rel-2 y))
(run 1 (r)
(fresh (x y)
(conde
((== 'a x) (tmp-rel y))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c))
但是,run 2
还是run 3
循环。
如果我使用condi
而不是conde
, 那么run 2
可以工作但run 3
仍然循环。
TRS2
(defrel (tmp-rel y)
(conde
((== 'c y) )
((tmp-rel-2 y))))
(defrel (tmp-rel-2 y)
(== 'd y)
(tmp-rel-2 y))
(run 3 r
(fresh (x y)
(conde
((== 'a x) (tmp-rel y))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((b e) (b f) (a c))
这没关系,只是顺序不符合预期。
请注意,(a c)
现在是最后。
TR1*
(define (tmp-rel y)
(conde
((== 'c y) )
((tmp-rel-2 y))))
;;
(define (tmp-rel-2 y)
(== 'd y)
(tmp-rel-2 y))
(run 2 (r)
(fresh (x y)
(conde
((== 'a x) (tmp-rel y))
((== 'b x) (conde
((== 'e y) )
((== 'f y)))))
(== `(,x ,y) r)))
;; => '((a c) (b e))
但是,run 3
循环。