让我们想象一个简单的家谱事实数据库,其中mother(M, C)
和father(F, C)
表示M
/ F
是孩子C
的母亲/父亲。< / p>
我写了一条规则,找到一个孩子的已知父母(零,一个或两个):
parents(C, M, F) :-
(mother(M, C) -> true; true),
(father(M, C) -> true; true).
如果已知M
和F
,则会将其绑定,否则会将其解除绑定。
它工作正常,这意味着对于一组事实:
mother(m1, c1).
father(f1, c1).
mother(m2, c2).
对parents(c1, M, F)
的调用会返回:
M = m1,
F = f1.
而parents(c2, M, F)
返回:
M = m2.
但使用箭头操作符对我来说似乎有点奇怪。我错过了什么基本的东西?可以避免/简化(X -> true ; true)
来电吗?
任何帮助表示感谢。
干杯,
答案 0 :(得分:4)
从逻辑角度来看,此计划中的主要错误是不完整。
例如,考虑最常见的查询:
?- parents(X, Y, C). X = c1, Y = m1.
因此,报告<{1}}的没有解决方案。
但是存在这样的解决方案,如下所示:
?- parents(c2, Y, C). Y = m2.
那么,是,是否有解决方案?
如果您使用c2
和其他违反代码的逻辑纯度的构造,则几乎总是会出现错误。有关详细信息,请参阅logical-purity。
因此,从逻辑的角度来看,我只能建议避免这样的结构,因为它们打破了逻辑编程语言的主要优势:开始逻辑的能力< / em>关于你的节目。
相反,请关注您想要描述的关系的明确描述,并说明使它们成立的条件。这将允许您以合理的方式使用Prolog程序。
编辑:我觉得你更喜欢拙劣的程序。为此,我建议 (->)/2
。 ignore/1
将ignore(Goal)
称为Goal
,成功。您可以使用它来简化程序,并确保它仍然不完整。
答案 1 :(得分:1)
Prolog是一种真实的脚踏实地编程语言。它有一个纯粹的子集。 两个都有自己的位置。
once( (A ; true) )
是问题的答案&#34;我们如何简化(A -> true; true)
&#34;。
如果你想要更高的纯度,你可以使用&#34;软剪切来编写(A *-> true ; true )
&#34; *->
承认来自成功A
的所有解决方案,并且仅在A
未生成任何}的情况下切换到不成功的分支1} EM>。另见例如我的this answer可以进行更多讨论。
另一个变体是(A ; \+ A)
。