我目前正在学习The Reasoned Schemer学习miniKanren。
我陷入了第5章第62帧的练习:(run* (x) (flatten_o (a) x))
,为什么输出中有三个列表?
提前多多感谢。
答案 0 :(得分:3)
好问题!这些额外的清单来自哪里?
问题出在else
定义的flatteno
子句中。 else
子句处理s
是符号(此处为符号a
)的情况。但是,该子句还允许s
为空列表或一对!这就是我们看到三个列表而不是一个列表的原因---额外的两个列表是由递归调用生成的,这些调用由于else
子句接受s
的非符号值而成功。
在miniKanren的更高版本中,我们添加了特殊约束,例如symbolo
和=/=
,以防止此类行为。例如,以下是相同的查询,flatteno
,用fast-miniKanren(https://github.com/webyrd/faster-miniKanren)编写:
(define flatteno
(lambda (s out)
(conde
((== '() s) (== '() out))
((fresh (a d res-a res-d)
(== (cons a d) s)
(flatteno a res-a)
(flatteno d res-d)
(appendo res-a res-d out)))
((symbolo s) (== (cons s '()) out)))))
(run* (x)
(flatteno '(a) x))
=>
((a))
请注意在symbolo
中使用flatteno
约束以确保s
是符号。
您可以在本文中找到这些约束的非“小书”解释:
http://webyrd.net/quines/quines.pdf
我们正试图弄清楚如何以Little Book格式包含这些约束的描述。约束的实现有点涉及,这使得很难适应Little Book!
希望这有帮助!
干杯,
- 威尔