我希望将变量绑定到几个原子,以便稍后它将与其中一个原子统一。 直觉上它应该像这样工作(假设;是可能值的分离):
?- X = (apple; pear), X = apple.
X = apple.
?- X = (apple; pear), X = apple, X = pear.
false.
?- X = (apple; pear; orange), X = (apple; orange).
X = (apple; orange).
?- X = (apple; orange), X = (pear; orange).
X = orange.
?- X = (apple; orange), X = pear.
false.
正如您所见,这个想法接近于类型层次结构的概念。 所以,我想知道是否有一些内置的(元)谓词可以很容易地做这样的事情,或者如果有一些常见的方式使用某种数据结构来模拟这个,或者我必须构建这种类型的从头开始预测?
答案 0 :(得分:2)
正如你从其他答案中看到的那样,有一种直截了当的方式用Prolog表达这一点,使用析取(离开选择点),或明确推理集合及其交叉点。
另一种方法是使用约束,它允许你推迟目标,直到知道更多:你可以例如将你的原子映射到整数,然后将变量的成员资格表示为一个集合,因为它有一个特定的整数域,使用 CLP(FD)约束。或者,您可以使用属性变量或约束处理规则( CHR )实现一个自定义约束求解器,该解算器可以解释原子。两种情况下的关键优势在于您可以更自由地重新排序您的目标,并且在发布更多约束时隐式调用约束推理。
编辑:例如,请考虑使用 CLP(FD)约束来解决您的任务。通过最多的修改,以下示例适用于SICStus,SWI,YAP和其他系统。根据您的Prolog系统,您可能需要导入合适的库以使用其中一些谓词:
fruit_integer(apple, 0). fruit_integer(pear, 1). fruit_integer(orange, 2). variable_fruits(Var, Fruits) :- maplist(fruit_integer, Fruits, Integers), foldl(domain_, Integers, 1..0, D), Var in D. domain_(E, D0, D0 \/ E).
在这种情况下,关键的想法是将水果映射到整数,这样您就可以使用CLP(FD)约束来表达所有内容。
您的示例查询和答案::
?- variable_fruits(X, [apple,pear]), fruit_integer(apple, X). X = 0. ?- variable_fruits(X, [apple,pear]), fruit_integer(apple, X), fruit_integer(pear, X). false. ?- variable_fruits(X, [apple,pear,orange]), variable_fruits(X, [apple,orange]). X in 0\/2. ?- variable_fruits(X, [apple,orange]), variable_fruits(X, [pear,orange]). X = 2. ?- variable_fruits(X, [apple,orange]), fruit_integer(pear, X). false.
显然,您也可以在其他方向使用fruit_integer/2
,并将此类整数和域转换回 atoms 列表。我把这作为一个简单的练习。
正是由于这个原因,CLP(FD)约束被称为有限域的约束:所有有限域都可以映射到整数的有限子集。因此,CLP(FD)约束不仅对一般表示整数运算有用,而且对于任意有限集的推理也是有用的。有关详细信息,请参阅 clpfd 。
一些补充说明:
答案 1 :(得分:1)
您可以使用member/2
:
24 ?- member(X, [apple, pear]), member(X, [apple]).
X = apple ;
false.
25 ?- member(X, [apple, pear]), member(X, [apple]), member(X, [pear]).
false.
26 ?- member(X, [apple, pear, orange]), member(X, [apple, orange]).
X = apple ;
X = orange.
27 ?- member(X, [apple, orange]), member(X, [pear, orange]).
X = orange.
28 ?- member(X, [apple, orange]), member(X, [pear]).
false.
或者使用intersection/3
缩小可能值的范围,使用可能值列表对此进行建模:
35 ?- _X1=[apple, pear], intersection(_X1, [apple], X2).
X2 = [apple].
36 ?- _X1=[apple, pear], intersection(_X1, [apple], _X2),
intersection(_X2, [pear], X3).
X3 = [].
37 ?- _X1=[apple, pear, orange], intersection(_X1, [apple, orange], X2).
X2 = [apple, orange].
38 ?- _X1=[apple, orange], intersection(_X1, [pear, orange], X2).
X2 = [orange].
39 ?- _X1=[apple, orange], intersection(_X1, [pear], X2).
X2 = [].
答案 2 :(得分:0)
也许你正在使用错误的语法:
?- X = apple ; X = pear.
X = apple ;
X = pear.
但我会接受Will Ness的建议。
答案 3 :(得分:0)
虽然在我的回答中并不清楚问题是如何与类型层次结构相关的,但它是由后者触发的,本文给出了一个有效的解决方案: 优化的PROLOG编码类型的结构,GERALD PENN,1999。 使用 Colmerauer方法并简单地说:
'apple or pear' = f(0,_,1,1).
'pear or orange' = f(0,0,_,1).
'orange or apple' = f(0,X,X,1).
'apple' = f(0,1,1,1).
'orange' = f(0,0,0,1).
'pear' = f(0,0,1,1)
并且所有这些表示都遵循prolog匹配: 'apple or pear'包含'apple'和'pear', 用'苹果或梨'统一'苹果或橙子'给'苹果'。