2

我目前正在通过学​​习 The Reasoned Schemer 来学习 miniKanren。

我被困在第 5 章第 62 帧的练习中:(run* (x) (flatten_o (a) x))为什么输出中有三个列表?

4

1 回答 1

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

我们正试图弄清楚如何在小书格式中包含对这些约束的描述。约束的实现有点复杂,很难放在一本小书中!

希望这可以帮助!

干杯,

- 将要

于 2017-10-24T04:24:26.183 回答