Prolog maplist on inner term?

How to use maplist on inner term?

Assuming the KB is:

gate(not(o), i). 
gate(not(i), o).

gate(and(o, i), o).
gate(and(i, o), o).
gate(and(B, B), B).

bits([i,o,o,i,i]).

The following is not working: ?- bits(BITS), maplist(gate(not(X), Y), BITS, ANS)

How can I map over the list so that:

[i,o,o,i,i] -> [not(i), not(o), not(o), not(i), not(i)] ->[o,i,i,o,o]

This is to be done on any list length:

:- bits([A,B,C,D,E]), gate(not(A), Anew), gate(not(B), Bnew), gate(not(C), Cnew), gate(not(D), Dnew), gate(not(E), Enew), ANS = [Anew, Bnew, Cnew, Dnew, Enew].

So that the answer would be: ANS = [o, i, i, o, o]


Solution 1:

With a helper predicate:

not(A, Z) :-
    gate(not(A), Z).

?- bits(BITS), maplist(not, BITS, ANS).

ANS  = [o, i, i, o, o],
BITS = [i, o, o, i, i]

But if you are going to add two lines of helper, skip the gate() stuff and write directly:

not(o, i).
not(i, o).

?- bits(BITS), maplist(not, BITS, ANS).

ANS  = [o, i, i, o, o],
BITS = [i, o, o, i, i]

If you don't want to do that, or cannot change the database at all, the only way I know is using a lambda library such as yall in SWI Prolog, others may be available to write this:

?- bits(BITS), maplist([In, Out]>>gate(not(In), Out), BITS, ANS).

ANS  = [o, i, i, o, o],
BITS = [i, o, o, i, i]

(It might be bad form to name it not, but this is not/2 and the builtin is not/1 so I don't think it will clash).