Prolog:如何捕获术语或模式匹配的整个结果

时间:2013-09-09 10:23:33

标签: prolog pattern-matching

在Erlang和Haskell中,有一种方法可以捕获整个模式匹配。例如,在Erlang中:

% We can capture the whole match of list, and not only inner part of structure
% like head and tail.
match_list([H|T]=F) -> hd(F).

我想知道如何在Prolog中做到这一点。如何在没有手工重建的情况下获得整个术语:

match_list([H|T]) :-
    % quite awkward, how to back-reference to it automatically?
    F = [H|T], ...

我试图解决下一个任务。有很多家庭关系被指定为一组事实(类似于第4章Bratko书的一部分)。我想创建一个谓词,它从这组家族中返回特定的族。目前的解决方案如下:

family(
  person(tom, fox, date(7,may,1950), works(bbc,15200)),
  person(ann, fox, date(9,may,1951), unemployed),
  [
    person(pat, fox, date(5,may,1973), unemployed),
    person(doris, fox, date(8,may,1973), unemployed),
    person(kate, fox, date(5,may,1973), unemployed),
    person(jim, fox, date(6,may,1973), unemployed)]).
% ... here goes another family

foxs(F) :-
  family(person(_, fox, _, _), W, CL),
  family(H, W, CL),
  F = family(H, W, CL).

正如你所看到的,首先是狐狸目标查找家庭数据库并捕获妻子(W)和孩子(CL)。在第二个条款中,它捕获了丈夫(H)。第三,它重建了家庭。而且我不喜欢这些东西。在Erlang或Haskell中,我可以匹配家族并捕获它,因此不需要第二和第三部分。

我用谷歌搜索并堆叠溢出,但没有运气。也许有人可以指出我正确的方向?

PS:我使用SWI-Prolog。

2 个答案:

答案 0 :(得分:1)

使用Prolog的内置统一,这是模式匹配的概括。例如,怎么样:

match_list(List) :- List = [L|Ls], ... .

foxs/1示例中,由于F仅用于头部,因此您可以将显式统一((=)/2)拉入头部:

foxs(family(H, W, Cs)) :-
    family(person(_, fox, _, _), W, Cs),
    family(H, W, Cs).

但是,您可能更需要:

foxs(family(H, W, Cs)) :-
    H = person(_, fox, _, _),
    family(H, W, Cs).

答案 1 :(得分:0)

更短的模式可能是

foxs(F) :-
  F = family(person(_, fox, _, _), person(_, fox, _, _), _),
  call(F).  % was F.