我正在阅读the Reasoned Schemer。
我对conde
如何运作有一些直觉。
但是,我无法找到conde
/ conda
/ condu
/ condi
所做的正式定义。
我知道https://www.cs.indiana.edu/~webyrd/,但这似乎有例子而不是定义。
某处有conde
,conda
,condi
,condu
的正式定义吗?
答案 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)
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)...)
同样如此)。
这就是全部。如果我们想要,我们甚至可以有更多类型的尝试目标,由不同类型的“||~
”运算符表示:
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存档通常的编程模式更加困难。