I have this very simple problem: write a Prolog program that implement the append Prolog function, that concatenate two strings and that work in the following way:
So I have the following two solutions and I am not so sure if my declarative interpretation is correct:
1) SOLUTION 1:
myappend1([],L,L).
myappend1([X|L1],L2,[X|L3]) :- myappend1(L1,L2,L3).
I think that I can read it in a declarative way as following:
The fact say that: if the first list (L1) is empty and the second list (L2) is not empty then it is TRUE that the concatenation of L1*L2 is L2
If the fact it is not true it means that the first list is not empty and so the concatenation of the first list and the second list it is not true that is the second list
So, let me call the first list L1, the second list L2 and the third list L3 then the rule responds TRUE if L3 is the concatenation of L1 and L2, false otherwise
I think that the declarative meaning of this rule is that: the head of the rule is true if the body of the rule is true.
When it reach the base case in which I have the demonstrated fact myappend1([],L,L). that is true, the program do backtracking at the previous past and because the X element of the first list unified with the X element of the third list it can do that also this computational pass it is TRUE and go back until reach the first assertion
Is this a correct declarative interpretation?
2) SECOND SOLUTION:
myappend2([],L,L).
myappend2(L1,L2,L3) :- L1=[X|T], % Dimostra questo predicato AND
L3=[X|L4], % Dimostra questo predicato AND
myappend2(T,L2,L4). % Dimostra questa funzione
As in the previous solution the fact simply say that: if the first list (L1) is empty and the second list (L2) is not empty then it is TRUE that the concatenation of L1*L2 is L2
If the fact it is not true it means that the first list is not empty and so the concatenation of the first list and the second list it is not true that is the second list
If the fact it is not true Prolog call the rule and this rule means that: the head of the rule is true if the body of the rule is true.
In this case I can read it in this way:
The concatenation of L1 and L2 is L3 is TRUE if it is true that:
Is it correct?
for me it is so difficult reasoning in declarative way :-(
Like last time, you're adding restrictions that aren't present in the code. Don't feel bad about it, Prolog is very different and it will take time to get used to it.
Let's start.
append([], L, L).
You said:
If the first list (L1) is empty and the second list (L2) is not empty then it is TRUE that the concatenation of L1*L2 is L2
In fact this rule says nothing about whether L2 is empty--or even a list!--or not. It simply says that the empty list appended to something else is that something else. Observe:
?- append([], foo, X).
X = foo.
The declarative reading here is "the empty list appended to L is L."
If the fact it is not true it means that the first list is not empty and so the concatenation of the first list and the second list it is not true that is the second list
Yes, this is correct, but Prolog isn't probing that deeply into the body. It just says "the first list is not empty, so this rule does not match; moving on."
The next rule:
myappend1([X|L1], L2, [X|L3]) :- myappend1(L1,L2,L3).
Your commentary seems excessively complex to me. I would say that this rule says: "myappend1 of the list [X followed by L1] to L2 is the list [X followed by L3], if myappend1 of the list L1 to L2 is L3." The consequences of this reading, however, are exactly as you describe.
Your understanding of what is happening in the first version is, therefore, correct.
The second solution is, mechanically, exactly the same as the first solution. The only difference is that we have moved the unification from the head of the clause into the body. This version is, to my eyes, clearly inferior, because all it has done is create extra work for the reader.
I think the problem you're having, so far, is that your declarative reasoning is intimately tied up with Prolog's engine of computation. A purer declarative reading like the ones I have supplied are simpler and look more like what the Prolog is saying (and have less to do with how it is evaluated).
It will take practice for you to separate these notions, but I think it will help you get better (clearly it's something you're concerned about). In the meantime there's nothing wrong with coming here and asking for help like you've been doing when you get confused. :)
Let me know if I can help more!