Всякий раз, когда цель не достигает цели, которую вы ожидаете достичь, рассматривайте это как возможность выучить (краткая форма для логики заработать = заработать логику). В конце концов, это пролог, означавший Программирование в логике . Так где же логика в вашей программе?
На данный момент ваша программа не работает, но вы ожидали, что она будет успешной. Где виновник? Давайте обобщим вашу программу так, чтобы полученная программа все еще не работала, но была намного меньше. Существует два простых способа обобщить программу:
Мы можем сделать это довольно слепо. Не нужно понимать вашу программу. Просто проверьте, что цель все еще не достигнута. Вот что я придумал с первой попытки:
:- op(950, fy, *).
* _G_0. % ignore the argument _G_0
sum([], <b>_<s>/*0*/</s></b>).
sum([<b>_<s>/*[_,Head]*/</s></b>|[_,Tail]], Sum) :-
* <s>sum([_,Tail], Sum2)</s>,
* <s>Sum is Head+Sum2</s>.
?- sum([<b>_<s>/*[a, 1]*/</s></b>, <b>_<s>/*[b, 2]*/</s></b>, <b>_<s>/*[c, 3]*/</s></b>, <b>_<s>/*[d, 4]*/</s></b>], Total).
false. % gnah - still fails
Одна проблема должна находиться в оставшейся видимой части. Слишком сложно понять? Позвольте Прологу объяснить это вам, запросив самый общий запрос :
| ?- sum(Xs, Sum).
Xs = []
; Xs = [_A,_B,_C].
Таким образом, возможны только две длины списков: пустой список и список из трех элементов. Обратите внимание, что в настоящее время у нас есть обобщенная версия предиката. Так что нет гарантии, что мы найдем решения для обеих длин. Однако мы можем быть на 100% уверены, что для всех остальных вариантов решения не будет.
Вернемся к исходной программе и зададим самый общий запрос:
?- sum(Os, Total).
Os = [], Total = 0
; false.
О, нет , есть только одно решение. И даже ни одного решения для sum([_|_], Total)
.
Итак, давайте снова обобщим программу, но теперь относительно этой неудачной цели:
sum([], <b>_<s>/*0*/</s></b>).
sum([<b>_<s>/*[_,Head]*/</s></b>|[_,Tail|<b>_<s>/*[]*/</s></b>]], Sum) :-
sum([_,Tail], Sum2),
* <s>Sum is Head+Sum2</s>.
?- Os = [_|_], sum(Os, Total).
false.
В этой части должна быть еще одна ошибка. И на самом деле, цель sum([_,Tail], Sum2)
является виновником: речь идет о списке ровно из двух элементов, но правило требует как минимум три
Фактические исправления см. В других ответах.
Этот метод работает для чистых монотонных программ, таких как ваша.