Let's use if_/3 and (=)/3 (a.k.a. equal_truth/3), as defined by @false in this answer!
So here comes the new, logically pure find/3:
find(E0,E1,[X|Xs]) :-
   member_next_prev_list(E0,E1,X,Xs).
member_next_prev_list(E0,E1,X0,[X1|Xs]) :-
   if_(X0=E0, X1=E1, member_next_prev_list(E0,E1,X1,Xs)).
Let's run the queries mentioned by the OP / by other answers / by some comments:
?- find(a,X,[a,a,b]).
X = a.                      % succeeds deterministically
?- find(a,X,[a,Y,b]).
X = Y.                      % succeeds deterministically
?- find(a,b,[a,a,b]).
false.                      % fails
?- find(a,X,[a,a,b,c]).
X = a.                      % succeeds deterministically
?- find(b,X,[a,a,b,c]).
X = c.                      % succeeds deterministically
Now to something a little more general:
?- find(X,Y,[a,a,b,c]).
X = a, Y = a ;
X = b, Y = c ;
false.
What about the most general query? As the code is pure, we get logically sound answers:
?- find(X,Y,List).
List = [            X,Y|_Z] ;
List = [_A,         X,Y|_Z], dif(_A,X) ;
List = [_A,_B,      X,Y|_Z], dif(_A,X), dif(_B,X) ;
List = [_A,_B,_C,   X,Y|_Z], dif(_A,X), dif(_B,X), dif(_C,X) ;
List = [_A,_B,_C,_D,X,Y|_Z], dif(_A,X), dif(_B,X), dif(_C,X), dif(_D,X) ...
Edit 2015-05-06
Here's a more concise variant, unimaginatively called findB/3:
findB(E0,E1,[X0,X1|Xs]) :-
   if_(X0=E0, X1=E1, findB(E0,E1,[X1|Xs])).
Like find/3, findB/3 is efficient in the sense of not leaving useless choicepoints behind, but it has higher memory use. 
findC/3 tries to reduce the memory use by hoisting the common expression [X1|Xs]:
findC(E0,E1,[X0|XXs]) :-
   XXs = [X1|_],
   if_(X0=E0, X1=E1, findC(E0,E1,XXs)).