foo(X,Z) :-
bar(X,Y),
baz(Y,Z).
Traditionally if you call foo(1,Z) it will try to find an answer for bar(1,Y) first then feed that Y value into baz, if you call foo(X,3) it will still try to find values for bar(X,Y) first. Sometimes that's okay because the engine will be like well yeah there's something that'll work so we'll say bar is true and move on to baz but some times it tell you to go suck eggs.You could write two different versions of foo
%foo(in,out)
foo(X,Z) :-
ground(X),
bar(X,Y),
baz(Y,Z).
%foo(out,in)
foo(X,Z) :-
ground(Z),
baz(Y,Z),
bar(X,Y).
but having to do that sucks. First it's forcing you to think about Prolog's implementation rather than the logical relationship between X and Z; second it's repetitive and forces you to keep both versions in sync with each other which is gonna get rough for more complex predicates.One of the things Mercury uses that mode info for is to re-arrange the body of foo(X,Y). So if you tell it that you will use both foo(in,out) and foo(out,in) it will compile two different versions of foo and dispatch appropriately.