Taking out the 2nd to last element - Prolog - prolog

I'm very new to Prolog and am trying to figure out exactly what is happening with this (function?) that takes out the 2nd to last element in a list.
remove([],[]).
remove([X],[X]).
remove([_,X],[X]).
remove([X|Xs], [X|Ys]) :-
Xs = [_,_|_],
remove(Xs,Ys).
I'm familiar with pattern matching, as I've done a little work in SML. The first one is clearly the base case, returning the empty list when we break it down. The second returns the same variable when there is only one left. The third looks as if it returns the last element, disregarding the 2nd to last? As for the inductive case, it will attach the head of the list to the new list if ...... (This is where I get completely lost). Could anyone explain what's happening in this function so I can have a better understanding of the language?

Elaborating on CapelliC's explanation:
remove([],[]).
An empty list is an empty list with the second-to-last element removed.
remove([X],[X]).
A single-element list is itself with the second-to-last element removed.
remove([_,X],[X]).
A two-element list with the second to last element removed is a list of one element consisting of the last element of the two-element list.
remove([X|Xs], [X|Ys]) :-
Xs = [_,_|_],
remove(Xs,Ys).
The second list is the first list with the second element removed, and share the same first element, IF:
The tail of the first list consists of at least two elements, AND
The tail of the second list is the tail of the first list with the second to last element removed

A set of clauses is a predicate, or procedure.
All first three are base cases, and the recursive one copies while there are at least 3 elements in the first list.
I would describe the behaviour like 'removes pre-last element'.

So, how to declaratively read
remove([X|Xs], [X|Ys]) :-
Xs = [_,_|_],
remove(Xs,Ys).
Most important is that you first realize what the :- actually means.
Head :- Body.
It means: Whenever Body holds, we can conclude that also Head holds. Note the rather unintuitive direction of the arrow. It goes right-to-left. And not left-to-right, as often written informally when you conclude something. However, the error points into the direction of what we get "out of it".
To better see this, you can enter Body as a query!
?- Xs = [_,_|_], remove(Xs,Ys).
Xs = [A, B], Ys = [B]
; Xs = [A, B, C], Ys = [A, C]
; ... .
So we get all answers, except those where Xs has less than two elements.
Please note that procedurally, things happen exactly in the other direction - and that is very confusing to beginners. Even more so, since Prolog uses two "non-traditional" features: chronological backtracking, and variables - I mean real variables, meaning all possible terms - not these compile time constructs you know from imperative and functional languages. In those languages variables are holders for runtime values. Concrete values. In Prolog, variables are there at runtime, too. For more to this, see Difference between logic programming and functional programming
There is also another issue, I am not sure you understood. Think of:
?- remove(Xs, [1,2]).
Xs = [1, A, 2]
; false.
What is removed here? Nothing! Quite the contrary, we are adding a further element into the list. For this reason, the name remove/2 is not ideal in Prolog - it reminds us of command oriented programming languages that enforce that some arguments are given and others are computed. You might at first believe that this does not matter much, after all it's only a name. But don't forget that when programming you often do not have the time to think through all of it. So a good relational name might be preferable.
To find one, start with just the types: list_list/2, and then refine list_removed/2 or list__without_2nd_last/2.

Annotated:
remove( [] , [] ) . % removing the 2nd last element from the empty list yields the empty list
remove( [X] , [X] ) . % removing the 2nd last element from a 1-element list yields the 1-element list.
remove( [_,X] , [X] ) . % removing the 2nd last element from a 2-element list yields the tail of the 2-element list
remove( [X|Xs] , [X|Ys] ) :- % for any other case...
Xs = [_,_|_], % * if the tail contains 2 or more elements, the list is 3 elements or more in length
remove(Xs,Ys). % we simply prepend the head of the list to the result and recurse down.
It should be noted that the last clause could re-written a tad more clearly (and a little more succinctly) as:
remove( [X1,X2,X3|Xs] , [X1|Ys] ) :- % for any other case (a list of length 3 or more)
remove([X2,X3|Xs],Ys). % we simply prepend the head of the list to the result and recurse down.
Or as
remove( [X1|[X2,X3|Xs]] , [X1|Ys] ) :- % for any other case (a list of length 3 or more)
remove([X2,X3|Xs],Ys). % we simply prepend the head of the list to the result and recurse down.

Related

What does the following recursive Prolog call output?

I'm trying to learn prologue, but man am I having trouble.
I have an example below as well as what it outputs, and I'm clearly stuck on some concepts but not sure what.
output([]).
output([c|R]):- output(R), !, nl.
output([X|R]) :- output(R), write(X).
?- output([a,b,c,d,e]).
Answer:
ed
ba
true.
Correct me if I'm wrong, but here is what I understand so far...
When we call output([a,b,c,d,e]).
prologue looks for a solution using unification,
it tries output([]) and fails, so it proceeds to the second output([c|R]) which then passes the tail of the list recursively into output([c|R]) until it hits the base case of output([]).
Now I get confused...It then hits the cut which locks R to [] and c with a value of e? how does the output afterwards happens? I'm really confused.
I think you're having a fundamental misunderstanding of what Prolog is doing and what unification is about. In Prolog when you make a query such as output([a,b,c,d,e]). Prolog will start from the beginning of your asserted facts and predicates and attempt to unify this term (your query) with a fact or the head of a predicate.
Unification
We need to stop here for a moment and understand what unification is. In Prolog, the operator =/2 is the unification operator and can be used to query the unification of two terms, term1 = term2. This query will succeed if term and term2 can be successfully unified. How can they be successfully unified? This can happen if there is a binding of variables in term1 and term2 such that the terms become, essentially, identical (by "essentially" I mean they might differ only in syntactic representation but are truly identical when in canonical form - see details below on what that is).
Here are examples of unification attempts that fail. You can enter these at a Prolog prompt and it will show immediate failure.
a = e. % This fails because the atom `a` is different than the atom `e1`
% There are no variables here that can change this fact
foo(X) = bar(Y)
% This fails because the functor `foo` is different than
% the functor `bar`. There's no way to get these terms to match
% regardless of how the variables `X` or `Y` might be instantiated
foo(a, Y) = foo(b, Y)
% This fails because no matter how the variable `Y` is instantiated
% the 1st argument of `foo` just cannot match. That is, the atom
% `a` doesn't match the atom `b`.
foo(a, b, X) = foo(a, b)
% This fails because the `foo/3` and `foo/2` have a different
% number of arguments. No instantiation of the variable `X` can
% change that fact
[1,2] = [1,2,3] % Fails because a list of 2 elements cannot match a list of 3 elements
[] = [_|_] % Fails because the empty list cannot match a list of at
% least one element.
[a,b,c] = [x|T] % Fails, regardless of how `T` might be bound, because `[a,b,c]`
% is a list whose first element is `a`
% and `[x|T]` is a list whose first element is `x`. The
% atoms `a` and `x` do not and cannot match.
Here are examples of successful unifications. You can test these as well at a Prolog prompt and you should get success or, if variables are involved, get at least one solution showing binding of variables that causes it to succeed:
a = a. % Trivial case: an atom successfully unifies with itself
X = a. % Succeeds with `X` bound to `a`
foo(X) = foo(a). % Succeeds with `X` bound to `a`
[a,b,c] = [a|T] % Succeeds with `T` bound to `[b,c]` because the first element
% `a` is the same in both cases.
[1,2,3] = [H|T] % Succeeds with `H` bound to 1, and `T` bound to `[2,3]`
% since `[1,2,3]` is equivalent to `[1|[2,3]]` (they are two
% different syntaxes representing the same term)
Just an aside: Prolog list syntax
We're writing lists using a form that's familiar from other languages. So [] is an empty list, and [1,2,3] is a list of the 3 elements 1, 2, and 3. You can also have lists inside of lists, or any terms in a list for that matter. This, for example, is a valid list of 3 elements: [a, [1,foo(a)], bar(x,Y,[])]. The first element is a, the second is a list of two elements, [1, foo(a)], and the third element is bar(x,Y,[]). In Prolog, you can also write a list in a form that describes the first of one or more elements and a tail. For example [H|T] is a list whose first element is H and the rest of the list is T (itself a list). A list of at least two elements could be written as [H|T] and you'd know that T has at least one element. Or you could write it as [H1,H2|T] and explicitly indicate the first two elements and understand that T would be a list of zero or more arguments. The first elements are individual elements of the list, and the tail is a list representing the rest of the list. The following forms all represent the list [a,b,c,d,e]:
[a,b,c,d,e]
[a|[b,c,d,e]]
[a,b|[c,d,e]]
[a,b,c|[d,e]]
[a,b,c,d|[e]]
[a,b,c,d,e|[]]
If you had a list, L, and wanted prolog to ensure that L had at least two arguments, you could unify L with an anonymous list of 2 elements: L = [_,_|_]. This will only succeed if L is a list of at least two elements.
Another aside: canonical form
Prolog, though, has what it calls a canonical form for terms which is its fundamental representation of a given term. You can see the canonical form of a term by calling write_canonical(Term):
| ?- write_canonical([a,b,c]).
'.'(a,'.'(b,'.'(c,[])))
yes
So that's interesting, what on earth is that? It doesn't look like a list at all! It's actually the canonical form in Prolog of what a list really looks like to Prolog (if you want to think of it that way). The fundamental term form in Prolog is a functor and zero or more arguments. The atom a is a term which could be viewed as a functor a with no arguments. The term foo(1,X) has functor foo and arguments 1 and X. The list [a,b,c] written that way is just a convenient syntax for programmers that make it easy to read. A list is actually formed by the functor '.' and two arguments: the head and the tail. So the list [H|T] in general is '.'(H,T) and the empty list [] is just itself, an atom representing the empty list. When Prolog unifies (or attempts to unify) two lists, it's really looking at a list as '.'(H, T) so it matches the '.' functor, then attempts to match arguments. In the case of multiple elements, it's a recursive match since T is itself a list.
Expressions in Prolog such as X + 3 are also a syntactic convenience for the canonical form, '+'(X, 3).
Back to our story
As we were saying, when you query output([a,b,c,d,e])., Prolog tries to unify this with heads of predicate clauses or facts that you have already asserted. Here's what you have asserted:
output([]).
output([c|R]):- output(R), !, nl.
output([X|R]) :- output(R), write(X).
Starting from the top, Prolog attempts this unification:
output([a,b,c,d,e]) = output([])
This fails since there are no variables to change the terms to make them match. It fails because the list [a,b,c,d,e] and the empty list [] cannot match.
On to the next clause:
output([a,b,c,d,e]) = output([c|R])
This can only succeed if the unification [a,b,c,d,e] = [c|R] can succeed with some binding of R. You can look at this as [a|[b,c,d,e,]] = [c|R]. Clearly, for this unification to succeed, the first element of each list must match. But a and c don't match, so this fails.
On to the next one:
output([a,b,c,d,e]) = output([X|R])
Prolog attempts then to unify [a,b,c,d,e] with [X|R], or [a|[b,c,d,e]] with [X|R]... and this succeeds since X and R are variables and they can be bound as X = a and R = [b,c,d,e]. Now the body of the clause can be executed:
output([b,c,d,e]), write(a).
Before we can get to the write(a), the call output([b,c,d,e]) must execute first and succeed. Following the same logic above, the the first and second clauses of the output/1 predicate do not match. But the 3rd clause matches again with [b,c,d,e] = [X|R] resulting in X = b and R = [c,d,e]. Now the body of this clause is executed again (and you must remember we're now one level deep in a recursive call... the above call to output([b,c,d,e]) is pending awaiting the result):
output([c,d,e]), write(b).
Now it gets more interesting. The first clause of output/1 still doesn't match since [c,d,e] = [] fails. But the second clause now does match since [c,d,e] = [c|R] succeeds with the binding R = [d,e]. So that body is executed:
output([d,e]), !, nl.
Now we need to chase down the call to output([d,e]) (we're now another level deep in recursion remember!). This one fails to match the first two clauses but matches the 3rd clause, by [d,e] = [X|R] with bindings X = d and R = [e].
I could keep going but I'm getting tired of typing and I do have a real job I work at and am running out of time. You should get the idea hear and start working through this logic yourself. The big hint moving forward is that when you finally get to output([]) in a recursive call an you match the first clause, you will start "unwinding" the recursive calls (which you need to keep track of if you're doing this by hand) and the write(X) calls will start to be executed as well as the !, nl portion of the second clause in the case where c was matched as the first element.
Have fun...
The main problem with your reasoning is that c is not a variable but an atom. It cannot be unified with any other value.
So with your example input, for the first 2 calls it will not execute output([c|R]) (since a nor b can be unified with c), but it goes on to output([X|R]) instead. Only for the third call, when the head is c, the former clause is called. After this it will call the latter clause another 2 times for d and e, and then it hits the base case.
From that point on we can easily see the output: if first writes 'e', then 'd', then a new line (for the time we matched c), ad then b and a. Finally you get true as output, indicating that the predicate call succeeded.
Also note that due to the cut we only get a single output. If the cut wasn't there, we would also get edcba, since the c case would also be able to match the last clause.

How to compare lists length Prolog

I'm new at Prolog and i was trying to solve some exercises and I found this one twice_as_long(L1,L2) that succeeds if the list L2 is twice as long as the list L1.
Do NOT compute the lengths of the lists.
twice_as_long([],[]).
true.
?- twice_as_long([a],[1,2]).
true.
?- twice_as_long([a,b],X).
X = [_G328, _G331, _G334, _G337] ;
false
I want some hint please cuz i don't want to compare lengths like what they said .
We can generalize your second example as a rule:
twice_as_long([_],[_,_]).
But we can do better:
twice_as_long([_|T1], [_,_|T2]) :- twice_as_long(T1,T2).
That, with the base case from you first example, will do the job.
With respect to Prolog conventions, given a predicate of the form type_of_relationship(X,Y), it's pretty customary to read it as a declaration of fact along the lines of
X has a type_of_relationship with Y.
So, let's flip the order of the arguments: twice_as_long(X,Y) asserts that X is twice as long as Y.
Given that, and amplifying the answer from #ScottHunter, Let's break things down into simple cases.
First, your example shows a case that should fail as succeeding.
twice_as_long([],[]).
asserts that the empty list is twice as long as itself, something that is manifestly untrue: the empty list is of length zero and twice zero is still..zero. So that case should be discarded.
There is, however, the simplest case possible:
twice_as_long( [_,_] , [_] ) .
an assertion that a list of length 2 is twice as long as a list of length 1.
Then, there is the generic case:
twice_as_long( [_,_|Xs] , [_|Ys] ) :-
twice_as_long(Xs,Ys) .
in which we say that a list of 2 or more items is twice as long as a list of 1 or more items...
IF, the remainder of the first list is twice as long as the remainder of the second list, where the remainders are obtained by removing the first 2 items from the first list and just 1 item from the second list.
That gives us this as the solution:
twice_as_long( [_] , [_,_] ) .
twice_as_long( [_|Xs] , [_,_|Ys] ) :- twice_as_long(Xs,Ys) .
The predicate will succeed when you get to the simple base case, and fail otherwise.

SWI-Prolog predicate example part 2

Can someone please help me in transforming this to match this updated requirement?
Define a predicate strikeDuplicates(X,Y) that succeeds if and only the list Y would
be obtained if one were to remove the second and subsequent occurrences of each element
from list X. (You might read strikeDuplicates (X,Y) as list X without duplicates
is list Y.) The strikeDuplicates/2 predicate need not work well when X is an
unbound variable.
I asked a similar question two days ago asking this:
Define a predicate strike(X,Y,Z) that succeeds if and only if the list Z would be
obtained if one were to remove all occurrences of element X from list Y. The
strike/3 predicate need not work well when Y is an unbound variable.
No one helped me so I had to do it by myself. That answer was this:
strike( _ , [] , [] ) .
strike( X , [X|T] , Z ) :- strike(X,T,Z) .
strike( X , [A|T] , [A|Z] ) :- dif(X,A) , strike(X,T,Z) .
dif(X,A).
A simple solution that doesn't preserve order is:
strike_duplicates([], []).
strike_duplicates([X| Xs], List) :-
( member(X, Xs) ->
strike_duplicates(Xs, List)
; List = [X| Tail],
strike_duplicates(Xs, Tail)
).
To preserve order, you need to keep track of the elements found so far while you traverse the list. A solution would be:
strip_duplicates(List, Set) :-
strip_duplicates(List, [], Set).
strip_duplicates([], _, []).
strip_duplicates([X| Xs], Found, List) :-
( member(X, Found) ->
strip_duplicates(Xs, Found, List)
; List = [X| Tail],
strip_duplicates(Xs, [X| Found], Tail)
).
The predicate member/2 is usually either a built-in predicate or available as a library predicate. Check your Prolog system documentation if necessary.
Well, the easy way would be to use the built-in predicate setof/3, but I suspect that's not what your professor wants.
Think about the problem for a second or two. A clear problem statement is often helpful (and in Prolog is often the solution itself):
To make the source list a set (unique elements) instead of a bag (allows duplication), you'll have to
Iterate over the source list
Track items you've already seen (the 'visited' list)
Add each item to the visited list only if the visited list doesn't already contain it.
Once you've done that you've got the desired result.
Here's a hint: a very common prolog idiom is the use of helper predicates that carry with it an accumulator. Often the helper predicate has the same functor, but a different arity. For example, to sum the values in a list (sum/2) we can use a helper sum/3 that carries an accumulator, seeded with 0:
sum(Xs,N) :- sum(Xs,0,N).
sum([],S,S).
sum([N|Ns],T,S) :-
T1 is T+N,
sum(Ns,T1,S)
.
You'll notice how unfication with the result is deferred until the final value has been computed.
You need to do something like that but using as an accumulator an [empty] list that will be extended with the unique values you discover.
Another hint: the built-in predicate member/2 will check if a term is a member of a list. It's written
member(X,[X|Xs]).
member(X,[_|Xs]) :- member(X,Xs).
So member(2,[1,2,3]) is true whilst member(2,[1,3]) is false.
Conversely, one can use member/2 to successively return each element of a list via backtracking: member(X,[1,2,3]) produces
X = 1 ;
X = 2 ;
X = 3 ;
false
Given those two notions, you should be able to figure out the solution. Come back and show us your code and we can help you. There is one other little gotcha, but I'm sure you'll figure it out.

Understanding difference lists (Prolog)

I'm having trouble understanding difference list, particularly in this predicate:
palindrome(A, A).
palindrome([_|A], A).
palindrome([C|A], D) :-
palindrome(A, B),
B=[C|D].
Could anyone help me follow what's happening?
palindrome(A, A).
palindrome([_|A], A).
palindrome([C|A], D) :-
palindrome(A, B),
B=[C|D].
Seeing the arguments to this predicate as a difference list, the first clause says, a list from A to A (i.e., an empty list) is a palindrome.
The second clause says, a one-element list is a palindrome, whatever that one element is.
Don't panic! Difference lists are just lists with explicit end "pointer"
A normal list, say [1,2,3], is a difference between its start and its end; the end of a normal list is always an empty list, []. That is to say, for a list [1,2,3] we are supposed to call this predicate as palindrome( [1,2,3], []) — namely, check whether the difference list [1,2,3] - [] is a palindrome.
From the operational point of view, a difference list is nothing but a (possibly open-ended) list with explicitly maintained "end pointer", for example: A - Z where A = [1,2,3|Z] and Z = []. Indeed, [1,2,3|[]] is the same as [1,2,3]. But when Z is not instantiated yet, the list A is still open ended - its "end pointer" Z can be instantiated to anything (but only once, of course, sans the backtracking).
If we were to instantiate Z later to an open-ended list, say, Z = [4|W], we'd get a new, extended difference list A - W where A = [1,2,3,4|W]. The old one would become A - Z = [1,2,3,4|W] - [4|W], i.e. still representing a prefix [1,2,3] of an open-ended list [1,2,3,4 ...]. Once closed, e.g. with W = [5], all the pairs of logvars still represent their corresponding difference lists (i.e. A - Z, A - W ...), but A is not open-ended anymore, so can't be extended anymore.
Instead of using the - functor, it is customary to just use both parts of the diff list definition as separate arguments to a predicate. When we always use / treat them as if they were two parts of a pair, then they form a pair, conceptually. It's the same thing.
Continuing. The third clause says, for [C|A]-D to be a palindrome, A-B must be a palindrome, and B must be [C|D]. A, D, B are lists, C is an element of a list. This might be confusing; let's use V instead. Also, use Z and Y instead of D and B, to remind us of "the end" of a list:
palindrome([V|A], Z):- palindrome(A, Y), Y=[V|Z].
V ................. V ----
^ ^ ^
| | |
| | Z
A Y = [V|Z]
Indeed, when the ...... core is a palindrome, putting two Vs around it gives us another palindrome.
The following is a summary that hopefully distills the best of the previous discussion, and adds one small but significant simplification.
First, the original question should be understood in the context of the problem at hand, which can be formulated as defining a Prolog predicate which will check whether a list is a palindrome, or more generally to generate palindromes. We wish to explore an implementation using difference lists, so we can begin as follows:
% List is a palindrome if List - [] is a palindrome:
palindrome( List ) :- palindrome(List, []).
(As explained elsewhere, if a list, List, is the concatenation of two lists
Front and Back, then Front can be viewed as being the difference
between List and Back, that is, Front can be regarded as equivalent to (List - Back).)
To define palindrome/2, we begin with the two "base cases", an empty list and a singleton:
% The empty list (L-L) is a palindrome:
palindrome(L, L).
% A singleton list, ([X|L] - L), is a palindrome:
palindrome([X|L], L).
Let us now turn to the general case.
If a list with more than one element is to be a palindrome, then it
will look like this: E ... E
where ... is a (possibly empty) palindrome.
Tacking on a tail, Tail, our list must look like: E ... E Tail
Writing this regular list as [E|Rest], we can now see that the original list ( [E|Rest] - Tail ) is a palindrome if (Rest - [E|Tail]) is a palindrome,
or in terms of our predicate palindrome/2:
palindrome( [E|Xs], Tail ) :- palindrome(Xs, [E|Tail]).
It's easy to see that this is equivalent to the original formulation.
That's it! Now we can, for example, generate templates for palindromes:
?- palindrome( X ).
X = [] ;
X = [_G1247] ;
X = [_G1247, _G1247] ;
X = [_G1247, _G1253, _G1247] ;
X = [_G1247, _G1253, _G1253, _G1247]
....

Sum of a list in prolog

I'm reading 'the art of prolog' book and I found an exercise that reads 'Define the relation sum(ListOfIntegers,Sum) which holds if Sum is the sum of the ListOfIntegers, without using any auxiliary predicate' .I came up with this solution:
sum([],Sum).
sum([0|Xs], Sum):-sum(Xs, Sum).
sum([s(X)|Xs], Sum):-sum([X|Xs],s(Sum)).
Which does not work exactly as I would want it to.
?- sum([s(s(0)),s(0),s(s(s(0)))],X).
true ;
false.
I was expecting X to be
s(s(s(s(s(s(0))))))
I thought that the problem is that I have to 'initialize' Sum to 0 in the first 'iteration' but that would be very procedural and unfortunately I'm not quite apt in prolog to make that work.
Any ideas or suggestions?
Your first clause should read
sum([], 0).
With that change, the vacuous true return goes away and you're left with one problem: the third clause reverses the logic of summation. It should be
sum([s(X)|Xs], s(Sum)) :- sum([X|Xs], Sum).
because the number of s/1 terms in the left argument to sum/2 should be equal to the number of them in the right argument.
The best way to localize the problem is to first simplify your query:
?- sum([0],S).
true.
?- sum([],S).
true.
Even for those, you get as an answer that any S will do. Like
?- sum([],s(s(0))).
true.
Since [] can only be handled by your fact, an error must lie in that very fact.
You stated:
sum([], Sum).
Which means that the sum of [] is just anything. You probably meant 0.
Another error hides in the last rule... After fixing the first error, we get
?- sum([0],Sum).
Sum = 0.
?- sum([s(0)],Sum).
false.
Here, the last clause is responsible. It reads:
sum([s(X)|Xs], Sum):-sum([X|Xs],s(Sum)).
Recursive rules are relatively tricky to read in Prolog. The simplest way to understand them is to look at the :- and realize that this should be an arrow ← (thus a right-to-left arrow) meaning:
provided, that the goals on the right-hand side are truewe conclude what is found on the left-hand side
So, compared to informal writing, the arrows points into the opposite direction!
For our query, we can consider the following instantiation substituting Xs with [] and X with 0.
sum([s(0)| [] ], Sum) :- sum([0| []],s(Sum)).
So this rule now reads right-to-left: Provided, sum([0],s(Sum)) is true, ... However, we do know that only sum([0],0) holds, but not that goal. Therefore, this rule never applies! What you intended was rather the opposite:
sum([s(X)|Xs], s(Sum)):-sum([X|Xs],Sum).
I'm not really following your logic, what with all the seemingle extraneous s(X) structures floating about.
Wouldn't it be easier and simpler to do something like this?
First, define your solution in plain english, thus:
The sum of an empty list is 0.
The sum of a non-empty list is obtained by adding the head of the list to the sum of the tail of the list.
From that definition, the prolog follows directly:
sum( [] , 0 ) . % the sum of an empty list is 0.
sum( [X|Xs] , T ) :- % the sum of an non-empty list is obtained by:
sum( Xs , T1 ) , % - first computing the sum of the tail
T is X + T1 % - and then, adding that the to head of the list
. % Easy!

Resources