conda,condi,conde,condu

时间:2012-06-01 02:08:40

标签: clojure scheme clojure-core.logic minikanren

我正在阅读the Reasoned Schemer

我对conde如何运作有一些直觉。

但是,我无法找到conde / conda / condu / condi所做的正式定义。

我知道https://www.cs.indiana.edu/~webyrd/,但这似乎有例子而不是定义。

某处有condecondacondicondu的正式定义吗?

4 个答案:

答案 0 :(得分:49)

在Prolog的术语中, condA “soft cut” *-> { {1}} “已提交的选项” - condU和软切割的组合,以便once表达 cut (once(A) *-> B ; false)

(A, !, B)

A *-> B ; C %% soft cut, condA once(A) *-> B ; C %% committed choice, condU 中,如果目标condA成功,则所有解决方案都会传递到第一个子句A,而没有替代条款{{1}尝试过。 B允许其参数目标仅成功一次(仅保留一个解决方案,如果有的话)。

C 是一个简单的分离, once/1 是一种分离,它在其成分的解决方案之间交替。


这是尝试忠实地将书的代码,逻辑变量和统一,转换成18行Haskell(其中并置是curried函数应用,condE表示 cons ) 。看看这是否澄清了事情:

  • 本书的顺序流组合(“ condI ”):
:
  • 替代流组合(“ mplus ”):
    (1)   []     ++: ys = ys
    (2)   (x:xs) ++: ys = x:(xs ++: ys)
  • 连续投放(“ mplusI ”):
    (3)   []     ++/ ys = ys
    (4)   (x:xs) ++/ ys = x:(ys ++/ xs)
  • 交替Feed(“ bind ”):
    (5)   []     >>: g = []
    (6)   (x:xs) >>: g = g x ++: (xs >>: g)
  • bindI目标组合(“ (7) [] >>/ g = [] (8) (x:xs) >>/ g = g x ++/ (xs >>/ g) ”):
OR
  • “交替condE”目标组合(“ (9) (f ||: g) x = f x ++: g x ”):
OR
  • condI”目标组合(“ (10) (f ||/ g) x = f x ++/ g x ”):
AND
  • 本书的“交替all”目标组合(“ (11) (f &&: g) x = f x >>: g ”):
AND
  • 特殊目标
allI

目标生成(可能是更新的)解决方案的流(可能是空的),给出(可能是部分的)问题解决方案。

重写 (12) (f &&/ g) x = f x >>/ g 的规则是:

    (13)  true  x = [x]  -- a sigleton list with the same solution repackaged
    (14)  false x = []   -- an empty list, meaning the solution is rejected

重写 all 的规则是:

(all)    = true
(all g1) = g1
(all g1 g2 g3 ...)  = (\x -> g1 x >>: (all g2 g3 ...)) 
                    === g1 &&: (g2 &&: (g3 &&: ... ))
(allI g1 g2 g3 ...) = (\x -> g1 x >>/ (allI g2 g3 ...)) 
                    === g1 &&/ (g2 &&/ (g3 &&/ ... ))

要获得最终的 condX (condX) = false (condX (else g1 g2 ...)) = (all g1 g2 ...) === g1 &&: (g2 &&: (...)) (condX (g1 g2 ...)) = (all g1 g2 ...) === g1 &&: (g2 &&: (...)) (condX (g1 g2 ...) (h1 h2 ...) ...) = (ifX g1 (all g2 ...) (ifX h1 (all h2 ...) (...) )) 的翻译,不需要实现该书的 {{1 }} condE ,因为它们进一步减少到简单的运算符组合,所有运算符都被认为是右关联

condI

因此在Haskell中不需要任何特殊的“语法”,普通的运算符就足够了。如果需要,可以使用ifE而不是ifI的任意组合。但是OTOH (condE (g1 g2 ...) (h1 h2 ...) ...) = (g1 &&: g2 &&: ... ) ||: (h1 &&: h2 &&: ...) ||: ... (condI (g1 g2 ...) (h1 h2 ...) ...) = (g1 &&: g2 &&: ... ) ||/ (h1 &&: h2 &&: ...) ||/ ... 也可以作为一个函数来实现,以接受要实现的目标的集合(列表,树等),这将使用一些智能策略来挑选它们可能或最需要的等等,而不仅仅是本书&&/运算符(或 &&: )中的简单二进制替换。

接下来,本书的 condI 可以由两个新的运营商||/ifI共同建模。我们可以以自然的方式使用它们,例如。

condA

可直观地被理解为“~~>”。

  • ||~”目标组合是产生一个“尝试”目标,必须使用失败继续目标进行调用:
g1 ~~> g2 &&: ... ||~ h1 ~~> h2 &&: ... ||~ ... ||~ gelse
  • IF g1 THEN g2 AND ... OR-ELSE IF h1 THEN ... OR-ELSE gelse”“尝试”目标和简单目标的目标组合简单地将其“尝试”目标称为第二个失败目标,因此它只不过是自动分组的便捷语法操作数:
IF-THEN

如果 (15) (g ~~> h) f x = case g x of [] -> f x ; ys -> ys >>: h OR-ELSE”运算符的约束力低于 (16) (g ||~ f) x = g f x ||~”运算符,并且也是正确关联的,{{1} }运算符的绑定能力仍然低于OR-ELSE等,上述示例的合理分组自动生成为

~~>

IF-THEN链中的最后一个目标必须是一个简单的目标。这没有任何限制,因为 ~~> 形式的最后一个条款无论如何都与简单的“&&:”相同 - 可以使用其目标的组合(或简单(g1 ~~> (g2 &&: ...)) ||~ ( (h1 ~~> (h2 &&: ...)) ||~ (... ||~ gelse)...) 同样如此)。

这就是全部。如果我们想要,我们甚至可以有更多类型的尝试目标,由不同类型的“||~”运算符表示:

  • 在成功条款中使用交替Feed(如果书中有一个,可以称之为 condA 的模型):
AND
  • 仅使用成功的解决方案流一次来生成剪切效果,以模拟 false
IF

最后,本书的 condAI (17) (g ~~>/ h) f x = case g x of [] -> f x ; ys -> ys >>/ h 的重写规则很简单:

condU

答案 1 :(得分:12)

Reasoned Schemer涵盖 conda (软切)和指令(已提交的选项)。你也会在William Byrd的出色dissertation on miniKanren中找到他们行为的解释。你已经将这篇文章标记为关于core.logic。要明确core.logic是基于最新版本的miniKanren而不是The Reasoned Schemer中提供的版本。 miniKanren总是交错分离目标 - condi ,并且交错变体不再存在。 conde 现在是 condi

答案 2 :(得分:1)

通过示例,使用core.logic:

conde将运行每个组,如果至少一个组成功则成功,返回所有成功组的所有结果。

user>  (run* [w q]
                (conde [u#]
                       [(or* [(== w 1) (== w 2)])
                        (== q :first)]
                       [(== q :second)]))
([_0 :second] [1 :first] [2 :first])

conda and condu:两个将在第一个成功的组(从上到下)停止

conda 仅返回第一个成功组的所有结果。

user> (run* [w q]
                (conda [u#]
                       [(or* [(== w 1) (== w 2)])
                        (== q :first)]
                       [(== q :second)]))
([1 :first] [2 :first])

指示仅返回仅来自第一个成功组的一个结果。

user> (run* [w q]
                (condu [u#]
                       [(or* [(== w 1) (== w 2)])
                        (== q :first)]
                       [(== q :second)]))
([1 :first])

不知道condi做了什么。

答案 3 :(得分:0)

根据ISO Prolog核心标准,将(,)/ 2,(;)/ 2和(->)/ 2等控制结构切成透明。在ISO Prolog核心标准中找不到(*->)/ 2,但通常Prolog系统会实现透明化。

这意味着无法翻译:

once(A) *-> B;C

进入A, !, B; C。因为后者可能会嵌入其他控制结构中,并且如果它们之间存在分离,则这些选择点也将被删除。另一方面,将其视为A -> B; C

似乎是合理的

简称为ISO Prolog核心标准 if-then-else 。这样定义的剪切行为对于例如在不引发异常的情况下打破重复循环很有用。使用if-then-else存档通常的编程模式更加困难。