我目前正在通过学习 The Reasoned Schemer 来学习 miniKanren。
我被困在第 5 章第 62 帧的练习中:(run* (x) (flatten_o (a) x))
为什么输出中有三个列表?
我目前正在通过学习 The Reasoned Schemer 来学习 miniKanren。
我被困在第 5 章第 62 帧的练习中:(run* (x) (flatten_o (a) x))
为什么输出中有三个列表?
好问题!这些额外的清单是从哪里来的???
问题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
我们正试图弄清楚如何在小书格式中包含对这些约束的描述。约束的实现有点复杂,很难放在一本小书中!
希望这可以帮助!
干杯,
- 将要