Write a predicate
allDistinct/1
whose parameter is a list (of symbols) and which succeeds if all symbols in the list are different.notin(A,[]). notin(A,[B|C]) :- A\=B, notin(A,C). allDistinct([]). allDistinct([_]). allDistinct([A|B]) :- notin(A,B), allDistinct(B).
-
3`allDistinct(B)` says that *any* list is all distinct! And... please indicate what you need help with. You haven't asked a question. – lurker Mar 08 '16 at 21:19
-
Besides unindented allDistinct(B) call I do not see why this code should not work. clause allDistinct([_]) seems to be redundant as well. – Raivo Laanemets Mar 10 '16 at 22:33
3 Answers
Following up on the previous sketch by @whd we can proceed like this.
Based on iwhen/2
we can succinctly define distinct/1
like so:
:- use_module(library(lists), [same_length/2]).
distinct(Es) :-
iwhen(ground(Es), (sort(Es,Fs),same_length(Es,Fs))).
Sample queries using SICStus Prolog 4.5.0:
| ?- distinct([1,2,3]). yes | ?- distinct([1,2,3.0]). yes | ?- distinct([1,2,3.0,2]). no | ?- distinct([1,2,3.0,X]). ! error(instantiation_error,_283)

- 18,496
- 4
- 54
- 166
Predicate sort/2
sorts and remove duplicates from list. You can use it, compare length(length/2
predicate) of new sorted list with old one if they differs there were some duplicated values.

- 1,819
- 1
- 21
- 52
This is one of those questions with a fair number of alternative, reasonable solutions. Assuming that common library predicates can be used, here is another one:
all_distinct(List) :-
\+ (
select(Element, List, Tail),
select(Element, Tail, _)
).
A performance advantage of this solution is that it stops scanning the list as soon as it finds a duplicated element. But is it faster than solutions based on the standard sort/2
predicate? Unclear as sort/2
is an highly optimized predicate in most Prolog systems. Plus, let's no forget that, unless we're sure that all list elements are bound, we should be safe and check it (see @repeat answer).

- 18,373
- 3
- 23
- 33