This is what I currently have. It has not been converted into has_type/2 but that is just a wrapper for consistency and ease of using.
** If you are up for a challenge you should try to do this for yourself. **
It is a simple predicate that returns true
or false
with predicate indicator list_difference(L1,L2)
.
Current code - click triangle to expand.
list_difference(L1,L2) :-
'$skip_list'(Length1,L1,_),
'$skip_list'(Length2,L2,_), !,
Length1 >= Length2,
list_difference(Length1,Length2,L1,L2).
list_difference(Length,Length,L1,L2) :-
\+ '$skip_list'(Length,L1,_),
\+ '$skip_list'(Length,L2,_),
ground(L1),
ground(L2),
L1 == L2, !.
list_difference(Length,Length,L1,L2) :-
'$skip_list'(Length,L1,_),
'$skip_list'(Length,L2,_),
ground(L1),
ground(L2),
L1 == L2, !.
list_difference(Length,Length,L1,L2) :-
var(L1),
var(L2),
L1 == L2, !.
list_difference(Length10,Length2,L1,L2) :-
Length10 > 0,
Length1 is Length10 - 1,
L1 = [_|T0],
list_difference(Length1,Length2,T0,L2).
No longer needing to tinker with it for corner cases. Also can probably reduce two of the clauses into one but it is late.
Example run.
?- list_difference(A,B).
false.
?- list_difference([1|T1],T2).
false.
?- list_difference([1,2,3],[2]).
false.
?- list_difference(A,A).
true.
?- list_difference([],[]).
true.
?- list_difference([1|T1],T1).
true.
?- list_difference([1],[1]).
true.
?- list_difference([1],[]).
true.
?- list_difference([1,2],[]).
true.
?- list_difference([1,2],[2]).
true.
Still need to do a lot more test cases.
EDIT
New version passing more extensive test cases.
Code
error:has_type(difference_list,(L1-L2)) :-
difference_list_type_check((L1-L2)).
difference_list_type_check((L1-L2)) :-
error:has_type(list_or_partial_list,L1),
error:has_type(list_or_partial_list,L2),
'$skip_list'(Length1,L1,_),
'$skip_list'(Length2,L2,_), !,
Length1 >= Length2,
difference_list_type_check(Length1,Length2,L1,L2).
difference_list_type_check(Length,Length,L1,L2) :-
ground(L1),
ground(L2),
L1 == L2, !.
difference_list_type_check(Length,Length,L1,L2) :-
var(L1),
var(L2),
L1 == L2, !.
difference_list_type_check(Length10,Length2,[_|T],L2) :-
Length10 > 0,
Length10 > Length2, !,
Length1 is Length10 - 1,
difference_list_type_check(Length1,Length2,T,L2).
difference_list_type_check(Length0,Length0,[H|T1],[H|T2]) :-
Length0 > 0,
Length is Length0 - 1,
difference_list_type_check(Length,Length,T1,T2).
Test cases
:- begin_tests(difference_list).
% Turn off singleton variable warnings in this module.
:- style_check(-singleton).
difference_list_type_check_test(success,01,(T1-T1)).
difference_list_type_check_test(success,02,([1|T1]-T1)).
difference_list_type_check_test(success,03,([1,2|T1]-T1)).
difference_list_type_check_test(success,04,([1,2,3|T1]-T1)).
difference_list_type_check_test(success,05,([1|T1]-[1|T1])).
difference_list_type_check_test(success,06,([1,2|T1]-[2|T1])).
difference_list_type_check_test(success,07,([1,2,3|T1]-[3|T1])).
difference_list_type_check_test(success,08,([1,2|T1]-[1,2|T1])).
difference_list_type_check_test(success,09,([1,2,3|T1]-[2,3|T1])).
difference_list_type_check_test(success,10,([1,2,3,4|T1]-[3,4|T1])).
difference_list_type_check_test(success,11,([1,2,3|T1]-[1,2,3|T1])).
difference_list_type_check_test(success,12,([1,2,3,4|T1]-[2,3,4|T1])).
difference_list_type_check_test(success,13,([]-[])).
difference_list_type_check_test(success,14,([1]-[])).
difference_list_type_check_test(success,15,([1,2]-[])).
difference_list_type_check_test(success,16,([1,2,3]-[])).
difference_list_type_check_test(success,17,([1]-[1])).
difference_list_type_check_test(success,18,([1,2]-[2])).
difference_list_type_check_test(success,19,([1,2,3]-[3])).
difference_list_type_check_test(success,20,([1,2]-[1,2])).
difference_list_type_check_test(success,21,([1,2,3]-[2,3])).
difference_list_type_check_test(success,22,([1,2,3,4]-[3,4])).
difference_list_type_check_test(success,23,([1,2,3]-[1,2,3])).
difference_list_type_check_test(success,24,([1,2,3,4]-[2,3,4])).
difference_list_type_check_test(success,25,([A|B]-B)).
difference_list_type_check_test(success,26,([A|B]-[A|B])).
difference_list_type_check_test(success,27,([A,B|C]-C)).
difference_list_type_check_test(success,28,([A,B|C]-[B|C])).
difference_list_type_check_test(success,29,([A,B|C]-[A,B|C])).
difference_list_type_check_test(success,30,([1,A|B]-B)).
difference_list_type_check_test(success,31,([1,A|B]-[A|B])).
difference_list_type_check_test(success,32,([1,A|B]-[1,A|B])).
difference_list_type_check_test(success,33,([A,1|B]-B)).
difference_list_type_check_test(success,34,([A,1|B]-[1|B])).
difference_list_type_check_test(success,35,([A,1|B]-[A,1|B])).
difference_list_type_check_test(fail ,01,([1|T1]-[1|T2])).
difference_list_type_check_test(fail ,02,([1,2|T1]-[2|T2])).
difference_list_type_check_test(fail ,03,([1,2,3|T1]-[3|T2])).
difference_list_type_check_test(fail ,04,([1,2|T1]-[1,2|T2])).
difference_list_type_check_test(fail ,05,([1,2,3|T1]-[2,3|T2])).
difference_list_type_check_test(fail ,06,([1,2,3,4|T1]-[3,4|T2])).
difference_list_type_check_test(fail ,07,([1,2,3|T1]-[1,2,3|T2])).
difference_list_type_check_test(fail ,08,([1,2,3,4|T1]-[2,3,4|T2])).
difference_list_type_check_test(fail ,09,([]-T2)).
difference_list_type_check_test(fail ,10,([1]-T2)).
difference_list_type_check_test(fail ,11,([1,2]-T2)).
difference_list_type_check_test(fail ,12,([1,2,3]-T2)).
difference_list_type_check_test(fail ,13,(T1-T2)).
difference_list_type_check_test(fail ,14,([1|T1]-T2)).
difference_list_type_check_test(fail ,15,([1,2|T1]-T2)).
difference_list_type_check_test(fail ,16,([1,2,3|T1]-T2)).
difference_list_type_check_test(fail ,17,([]-[1])).
difference_list_type_check_test(fail ,18,([1]-[2])).
difference_list_type_check_test(fail ,19,([1,2]-[3])).
difference_list_type_check_test(fail ,20,([1]-[1,2])).
difference_list_type_check_test(fail ,21,([1,2]-[2,3])).
difference_list_type_check_test(fail ,22,([1,2,3]-[3,4])).
difference_list_type_check_test(fail ,23,(a-b)).
difference_list_type_check_test(fail ,24,(a-T2)).
difference_list_type_check_test(fail ,25,((a)-T2)).
difference_list_type_check_test(fail ,26,([[]]-T2)).
difference_list_type_check_test(fail ,27,(a-a)).
difference_list_type_check_test(fail ,28,([]-a)).
difference_list_type_check_test(fail ,29,(a-[])).
test(is_type_success,[forall(difference_list_type_check_test(success,_,(L1-L2)))]) :-
difference_list_type_check((L1-L2)).
test(is_type_fail,[fail,forall(difference_list_type_check_test(fail,_,(L1-L2)))]) :-
difference_list_type_check((L1-L2)).
:- end_tests(difference_list).
Example run.
?- run_tests.
% PL-Unit: difference_list ................................................................ done
% All 64 tests passed
true.
If it was not for the help I received in this post of better understating what is a difference list I would not have been able write this code.