Простым решением является объявление предикатов динамическими:
:- dynamic(monthly_expense/1).
:- dynamic(onetime_expense/1).
Вызов предиката, который объявлен как динамический, но не определенный , просто завершается неудачей, вместо того, чтобы выдавать ошибку существования предиката.
P.S. Вы можете упростить свой код, используя стандартный предикат де-факто findall/4
:
expenses(Sum):-
findall(
MonthlyValue,
( monthly_expense(Y),
MonthlyValue is Y * 12
),
MonthlyValues
),
findall(
OneTimeValue,
( onetime_expense(Z),
OneTimeValue is Z
),
Values,
MonthlyValues
),
sum_list(Values, Sum).