Часть "она умножает сумму внутреннего списка на внешний список" не совсем понятна, но я думаю, вы имеете в виду, что, учитывая список [L1,...,Ln]
списков чисел, вы хотите вычислить S1*..*Sn
где Si
- сумма элементов в Li
(для каждого i
).
Я предполагаю существование plus
и mult
с их очевидным значением (например, plus(N,M,R)
верно именно тогда, когда R
равно N+M
). Сначала нам нужен предикат sum
такой, что sum(L,S)
выполняется тогда и только тогда, когда S
является суммой элементов L
. Если L
пусто, S
, очевидно, должно быть 0
:
sum([],0).
Если L
не пустой, а имеет форму [N|L2]
, то у нас есть S
должно быть N
плюс сумма S2
элементов в L2
. Другими словами, мы должны иметь и sum(L2,S2)
(чтобы S2 была суммой элементов L2
) и plus(N,S2,S)
. То есть:
sum([N|L2],S) :- sum(L2,S2), plus(N,S2,S).
Таким же образом вы можете определить предикат p
, который вы ищете. Мы хотим, чтобы p(L,R)
выполнялось тогда и только тогда, когда R
является произведением от S1
до Sn
, где L=[L1,...,Ln]
и sum(Li,Si)
для всех i
. Если L
пусто, R
должно быть 1
:
p([],1).
Если L
не пустой, но имеет форму [LL|L2]
, то мы имеем, что R
должно быть произведением 'S', суммы элементов LL
, и 'P', произведение сумм списков в L2
. Для S
у нас уже есть sum(LL,S)
, так что это дает нам следующее.
p([LL|L2],R) :- sum(LL,S), p(L2,P), mult(S,P,R).
Одна вещь, которую я хотел бы добавить, состоит в том, что, вероятно, не очень хорошая идея видеть эти предикаты как функции, которые вы могли бы использовать для императивного или функционального программирования. Это не тот случай, когда sumlist([1,..,n],X)
возвращает X = (result)
; (result)
- это значение для X
, такое, что sumlist([1,...,n],X)
является истинным. Это требует несколько иного мышления. Вместо того, чтобы думать "Как я могу вычислить X так, чтобы p (X) держалось?" Вы должны подумать: «Когда держится P (X)?» и используйте ответ («Хорошо, если q (X) или r (X)!»), чтобы составить предложения (p(X) :- q(X)
и p(X) :- r(X)
).