В вашем коде Пролога есть несколько элементарных проблем:
sum
— это атом Пролога, поэтому он никогда не будет унифицирован со списком.
- в Прологе мы определяем отношения между сущностями, и вам нужны предикаты аргументы для обращения к этим сущностям.
Поэтому вы не можете перевести код дословно. Тем не менее, возможен достаточно буквальный перевод HaskellProlog, если вы, например, вводите новый аргумент для хранения возвращаемого значения исходной функции. Ваш второй фрагмент идет в этом направлении, но он не является самодостаточным, а также содержит несколько ошибок. Например, xs
и sum
— это атомы, тогда как переменные в Прологе начинаются с заглавной буквы или символа подчеркивания.
Кроме того, если вы продолжите попытки буквального перевода, вы упустите возможность действительно извлечь выгоду из общих отношений. Типичные предикаты Пролога можно использовать не только в одном, но и в нескольких направлениях, и вы можете использовать их не только для вычислений, но и для тестировать и завершать частичные результаты.
Таким образом, вместо дословного перевода я хотел бы показать вам более идиоматическое решение этой задачи на Прологе.
Наше первое наблюдение, которое ясно из подписи типа: мы рассуждаем о целых числах. Таким образом, я рекомендую вам использовать ограничения CLP(FD) вашей системы Prolog для полностью декларативной целочисленной арифметики. Дополнительные сведения об этой функции см. в разделе clpfd.
Во-вторых, задачу можно рассматривать как «фильтрацию» списка, и для этого мы используем tfilter/3
, который предоставляется библиотека(reif).
Вот полное решение Prolog:
sublist_sum(Lss0, Sum, Lss) :-
tfilter(sum_intlist(Sum), Lss0, Lss).
sum_intlist(Sum, Ls, T) :-
sum(Ls, #=, Sum0),
zcompare(C, Sum0, Sum),
eq_truth(C, T).
eq_truth(=, true).
eq_truth(<, false).
eq_truth(>, false).
Думайте об этом предикате как о связанном списке Lss0
, сумме и втором списке Lss
, так что все заявленные вами требования удовлетворены. Заметьте, я не говорю, какие из этих аргументов «даны», потому что любой из них может быть указан полностью, частично или вообще не указан.
Ваш пример работает по мере необходимости:
?- sublist_sum([[1,2,3],[4,5,6]], 6, Ls).
Ls = [[1, 2, 3]].
Этот пример остается в пределах исходной функции: первый и второй аргументы полностью определены, а третий используется для представления «результата».
Однако, как это типично для Пролога, мы можем также использовать более общие запросы, в которых не только "результат", но и другие части остаются неопределенными. Ясно, что это выходит далеко за рамки функций, и дословный перевод исходного кода может не иметь такого преимущества.
Например:
?- sublist_sum([[1,2,N]], 6, Ls).
В этом случае мы оставили N
неуказанным и попросили Prolog рассмотреть все случаи, которые могут применяться для N
.
В ответ Пролог генерирует различные возможности, представленные в виде дизъюнкции:
N = 3,
Ls = [[1, 2, 3]] ;
Ls = [],
N in inf..2,
-3+_10694#=N,
_10694 in inf..5 ;
Ls = [],
N in 4..sup,
-3+_10662#=N,
_10662 in 7..sup.
Обратите внимание, как Ls
зависит от N
.
Мы также можем обобщить это далее и оставить даже сумму неопределенной:
?- sublist_sum([[A,B,C]], Sum, Ls).
Ls = [[A, B, C]],
A+B+C#=Sum ;
Ls = [],
A+B+C#=_15806,
_15806#=<Sum+ -1,
zcompare(<, _15806, Sum) ;
Ls = [],
A+B+C#=_15806,
Sum#=<_15806+ -1,
zcompare(>, _15806, Sum).
Опять же, Пролог перечисляет различные случаи.
Более того, мы можем специализировать запрос и использовать его для проверки связи:
?- sublist_sum([[1,2,3]], 5, []).
true.
Здесь мы спросили: Выполняется ли этот конкретный случай?, и Пролог отвечает true
, указывая, что отношение работает именно так, как предполагалось в этом случае.
person
mat
schedule
10.04.2017