Давайте упростить задачу немного по первому рассмотрении is_member/2
.
Вы пишете как:
is_member(X, [Head,Tail]):-
X == Head;
is_member(X, Tail).
Рассмотрим, как легко это неправильно это как:
is_member(X, [Head,Tail]):-
X == Head,
is_member(X, Tail).
Упражнение: Что я могу изменить?
По этой причине я рекомендую макет, как следующее:
is_member(X, [Head,Tail]):-
( X == Head
; is_member(X, Tail)
).
Теперь, на несколько тестов!
Во-первых, это всегда хорошая идея опубликовать наиболее общий запрос. Это просто спрашивает: Есть ли какие-либо решения?
?- is_member(E, Ls).
nontermination
Это не хороший знак!
Итак, давайте попробуем несколько конкретных корпусов. Например, является a
членом пустого списка?
?- is_member(a, []).
false.
Это хорошо! Это то, чего мы ожидали.
В таком случае a
является членом списка [a]
?
?- is_member(a, [a]).
false.
Это определенно неправильно!
Я рекомендую вам начать с этого времени, а затем перейти к более сложным определениям. Подойдите к нему на систематической основе:
- Запишите то, что должен держать.
- Попробуйте наиболее общий запрос, чтобы узнать, можете ли вы получить ответы от своей программы.
- Пробег конкретные тестовые примеры.
- Подумайте, что на самом деле предикат означает: Вы можете использовать предикат в нескольких направлениях, и во многих из этих случаев способ, которым вы описали предикат, не имеет смысла. Например, и список, и элемент уже могут быть , указанными, и в этом случае ничего не нужно «добавлять» или «удалять».
Чтобы найти причины неожиданного сбоя в программе, используйте program-slicing, например, используя следующее определение обобщать далеко цели:
:- op(920,fy, *).
*_.
Теперь вы можете написать:
is_member(X, [Head,Tail]):-
( *X == Head
; *is_member(X, Tail)
).
, который является массивного обобщения вашей оригинальной программы, а на самом деле декларативно эквивалент к:
is_member(X, [Head,Tail]) :- true.
Тестовый пример выше все еще не с этим фрагментом, который показывает, что программа еще слишком конкретных:
?- is_member(a, [a]).
false.
Блестящий ответ, спасибо Я отвечу на совет – user3667111
Также считаю, что исправил ошибку. С: 'is_member (X, [Голова | _]): - \t X == Голова. ' – user3667111
Это фиксирует конкретный тестовый пример' is_member (a, [a]) ', да. Однако попробуйте * небольшое * ** обобщение ** тестового примера: '? - is_member (a, [X]).' Это все еще ** не работает **. В целом я могу только рекомендовать ** избегать ** немонотонных предикатов, таких как '(==)/2'. Их можно безопасно использовать только в особых ситуациях и давать ** неправильные ** ответы в более общих случаях. Чтобы выразить, что два слагаемых ** равны **, используйте '(=)/2'. Он корректно работает во всех * направлениях. – mat