让我们来看看你的第一条规则。第一个目标总是成功,因为您询问的是具有单个元素的列表的长度是否为 1。只需在提示符处尝试:
?- length([A], 1).
true
相反,您可能希望在第一个列表的头部有一个不带括号的变量(例如[L|Ls]),并确保它是一个长度为 1 的列表:
?- length(L,1).
L = [_A]
第二条规则头部的第一个列表及其第一个目标也是如此。在您的第二个目标中,您尝试将 [H|N_List_T] 评估为带有 is/2 的算术表达式,以便 N_List 持有该值。除了这没有意义之外,您可以在提示符下尝试一下,看看这个目标如何无法成功:
?- N_List is [H|N_List_T].
ERROR!!
TYPE ERROR- string must contain a single character to be evaluated as an arithmetic expression: expected evaluable term, got [_131245|_131246]
相反,您想统一这两个术语:
?- N_List = [H|N_List_T].
N_List = [H|N_List_T]
但是,如果您将[H|N_List_T] 作为规则头部的第二个参数,您可以完全摆脱这个目标。此外,您可能希望在第二个列表的头部使用单一列表L,而不是变量H。此外,您还缺少一个案例,即第一个列表是[]。在这种情况下,第二个列表也是空的,因为空列表显然不包含任何单一列表。最后,我要指出,如果您选择一个更简单且更具声明性的名称,例如 listas_unitarias/2,它可能会增强代码的可读性。将所有这些放在一起,您最终可能会得到这样的谓词:
listas_unitarias([],[]).
listas_unitarias([L|Ls],[L|Ss]) :-
length(L,1),
listas_unitarias(Ls,Ss).
listas_unitarias([L|Ls],Ss) :-
length(L,X),
dif(X,1),
listas_unitarias(Ls,Ss).
您的第二个示例查询产生了所需的结果
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
对于您的第一个示例查询,结果略有不同:
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]] ? ;
no
唯一的单一列表在列表本身中。这会更有意义,因为第一个参数可能包含多个这样的列表。考虑以下情况:
?- listas_unitarias([[1],[2,3],[4],[]],U).
U = [[1],[4]] ? ;
no
但是,如果您打算一次获取一个单一列表,则谓词看起来会略有不同:
listas_unitarias2([L|_Ls],L) :-
length(L,1).
listas_unitarias2([_L|Ls],U) :-
listas_unitarias2(Ls,U).
查询结果也一样:
?- listas_unitarias2([[1,2],[1,2,3],[3]], U).
U = [3] ? ;
no
?- listas_unitarias2([[1],[2,3],[4],[]],U).
U = [1] ? ;
U = [4] ? ;
no
尤其是您的第二个示例查询:它会失败而不是生成空列表作为解决方案:
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],U).
no
?- listas_unitarias2([[1,2],[1,2,3],[3,4,5]],[]).
no
编辑:正如 cmets 中的 @false 所指出的,第三条规则中 length/2 和 dif/2 的组合使用不会因 [_,_|_] 而终止,因此查询
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]] ? ;
U = [[1],[2]] ? ;
...
也不会终止。但是,在这种情况下期望终止是合理的,因为以两个元素为首的列表肯定不能是单一的。因此,您可以考虑描述涵盖所有可能性的四种情况,而不是使用 length/2。 1)如果第一个列表是空的,那么第二个列表也是空的。 2)如果第一个列表的头部是[],它不在第二个列表中。 3) 如果第一个列表的头部是[A],它在第二个列表中。 4) 如果第一个列表的头部至少有两个元素,则它不在第二个列表中。
listas_unitarias([],[]). % case 1)
listas_unitarias([[]|Ls],Ss) :- % case 2)
listas_unitarias(Ls,Ss).
listas_unitarias([[A]|Ls],[[A]|Ss]) :- % case 3)
listas_unitarias(Ls,Ss).
listas_unitarias([[_,_|_]|Ls],Ss) :- % case 4)
listas_unitarias(Ls,Ss).
在此版本中,上述查询在找到唯一解决方案后终止:
?- listas_unitarias([[1],[_,_|_],[2],[3,4]],U).
U = [[1],[2]]
上面的其他查询产生相同的结果:
?- listas_unitarias([[1,2],[1,2,3],[3,4,5]],U).
U = []
?- listas_unitarias([[1,2],[1,2,3],[3]], U).
U = [[3]]
?- listas_unitarias([[1],[2,3],[4],[]],S).
S = [[1],[4]]