Search code examples
prolog

Prolog - how to check if a predicate succeeds more than once


I have a database of facts like this:

li(a,2).
li(b,3).
li(b,1).
li(c,2).
li(d,1).
li(d,1).

I need to write a predicate more(+Let) that succeeds if it exists more than one fact li(Let,_).

For example the queries more(b) and more(d) will succeed, but more(a) and more(c) will not. My idea was to check if li(Let,_) succeeds more than once, but I do not know how to do it.


Solution

  • Try findall/3:

    findall(X, li(d,X), L), length(L,N), N>1.
    

    Abstracting the d out and making a predicate is trivial. Right? :)


    If you don't want to use any of the predicates like findall, you can change the representation of your knowledge - bring it down one level, so to speak:

    my_knowledge(li, [a-2,b-3,b-1,c-2,d-1,d-1]).
    

    and then you can use SWI Prolog's predicate select/3 to handle it:

    select_knowledge(kn, key, R):-
      my_knowledge(kn,L),
      select_key(L,key,R).
    
    select_key(L,K,R):-
      select(K-X,L,L1) -> R=[X|R1], select_key(L1,K,R1)
      ; R = [].
    

    You can rewrite the last predicate as basic recursion over lists, and then tweak it to stop after getting first N results.