Сокращения - это действительно одна проблема: попробуйте, например, самый общий запрос
?- count(Ls, L, C).
и увидим, что это дает только одно решение, хотя очевидно, что их должно быть бесконечно много, потому что первым аргументом может быть список произвольной длины. Итак, сначала удалите все порезы. Другая проблема - это (\=)/2
, что не является истинным отношением: оно имеет смысл только в том случае, если его аргументы являются обоснованными. Вместо (\=)/2
используйте более общий предикат dif/2
, который доступен в SWI-Prolog, а также в других системах и ограничивает его аргументы разными терминами. Тогда ваш предикат будет работать во всех направлениях.
РЕДАКТИРОВАТЬ: я расширяю пункт «можно использовать во всех направлениях». Рассмотрим следующую версию list_term_count/3
, которая связывает список с количеством вхождений термина в этом списке, используя clpfd в дополнение к dif/2
:
list_term_count([], _, 0).
list_term_count([L|Ls], L, N) :-
list_term_count(Ls, L, N0),
N #= N0 + 1.
list_term_count([L|Ls], E, N) :-
dif(L, E),
list_term_count(Ls, E, N).
Мы можем использовать его самым общим вообразимым образом, оставляя все аргументы неопределенными, и получать правильные ответы:
?- list_term_count(Ls, E, N).
Ls = [],
N = 0 ;
Ls = [E],
N = 1 .
Чтобы точно перечислить все решения, мы можем использовать length/2
:
?- length(Ls, _), list_term_count(Ls, E, N).
Ls = [],
N = 0 ;
Ls = [E],
N = 1 ;
Ls = [_G167],
N = 0,
dif(_G167, E) .
Обратите внимание на ограничение dif/2
, которое возникает как остаточная цель и которое заставляет элемент списка отличаться от E
, когда N
равно 0
. Таким образом мы можем выразить бесконечный набор терминов, который не ограничен никакими другими способами, кроме отличия от E
.
Также допустим любой другой образец создания экземпляра. Например:
?- list_term_count([a], E, N).
E = a,
N = 1 ;
N = 0,
dif(E, a).
Или например:
?- list_term_count([X], a, N).
X = a,
N = 1 ;
N = 0,
dif(X, a).
Эта универсальность - одно из преимуществ использования чистых монотонных предикатов в ваших программах. Использование чистых целей также позволяет нам довольно свободно менять их порядок.
person
mat
schedule
15.09.2013
count/3
. - person luksan   schedule 21.09.2013