Указанная ошибка действительно имеет причину. :)
=\=/2
— это арифметический оператор, используемый для сравнения значения двух арифметических выражений на равенство, и он дает успех (истина), если они не равны. Это вызовет ошибку, если вы попытаетесь использовать его в нечисловых терминах.
Если вы хотите проверить, не идентичны ли термины, вы должны использовать \==
. Например,
?- a \== b.
true.
?- X \== a.
true.
Если вы хотите проверить «не унифицируемый», вы должны использовать \=
:
?- a \= b.
true.
?- X \= a. % X could be unified with 'a' to make them equal
false.
Это само по себе заставит ваш предикат работать, хотя он находит решение более одного раза:
?- remove_repeats([a,b,b,c,c,c,c,c,d], Result).
Result = [a, b, c, d] ;
Result = [a, b, c, d] ;
false.
?-
Хотя в логике нет ошибки, сама по себе, есть небольшая подчистка, которую можно было бы сделать.
remove_repeats([], []).
remove_repeats([X], [X]).
remove_repeats([X,X], [X]).
remove_repeats([X,Y], [X,Y]) :- X \= Y.
remove_repeats([H,H|T], R) :- remove_repeats([H|T], R).
remove_repeats([H1,H2|T], R) :-
H1 \= H2,
remove_repeats([H2|T], Z),
R = [H1|Z].
Предложение remove_repeats([X,X], [X]).
является избыточным, поскольку оно уже будет обработано remove_repeats([H,H|T], R) ...
, за которым следует remove_repeats([X], [X])
. Кроме того, пункт remove_repeats([X,Y], [X,Y]) :- X \= Y.
также является избыточным, поскольку его будут обрабатывать remove_repeats([H1,H2|T], R) ...
и remove_repeats([X], [X]).
. Затем мы можем привести в порядок последнее предложение, включив объединение R
в заголовок предложения:
remove_repeats([], []).
remove_repeats([X], [X]).
remove_repeats([H,H|T], R) :- remove_repeats([H|T], R).
remove_repeats([H1,H2|T], [H1|Z]) :-
H1 \= H2,
remove_repeats([H2|T], Z).
Избавление от избыточных правил также избавляет от избыточных результатов, поскольку у решения не будет более одного способа удовлетворить правила:
?- remove_repeats([a,b,b,c,c,c,c,c,d], Result).
Result = [a, b, c, d] ;
false.
?-
ИЗМЕНИТЬ
Как указал @false в своем комментарии, если вы используете SWI Prolog, у вас есть dif/2
доступный вам предикат, который было бы неплохо использовать вместо =\=/2
. Таким образом, указанное выше H1 \= H2
будет dif(H1, H2)
.
person
lurker
schedule
11.04.2014
=\=/2
— это арифметический оператор, используемый для сравнения, если два арифметических выражения оцениваются как неравные. Вы используете его для не чисел. Попробуйте вместо этого использовать\==
(термины не идентичны) или\=
(термины не поддаются унификации). - person lurker   schedule 11.04.2014