An exercise I'm trying out starts with the following facts
byCar(auckland,hamilton).
byCar(hamilton,raglan).
byCar(valmont,saarbruecken).
byCar(valmont,metz).
byTrain(metz,frankfurt).
byTrain(saarbruecken,frankfurt).
byTrain(metz,paris).
byTrain(saarbruecken,paris).
byPlane(frankfurt,bangkok).
byPlane(frankfurt,singapore).
byPlane(paris,losAngeles).
byPlane(bangkok,auckland).
byPlane(singapore,auckland).
byPlane(losAngeles,auckland).
...and asks the reader to define a predicate travel/3
such that, for example,
travel(valmont, losAngeles, T)
...will find solutions like
T = go(byCar(valmont, metz),
go(byTrain(metz, paris),
go(byPlane(paris, losAngeles)))).
This what I came up with:
travel(X,Y,go(byCar(X,Y))):-byCar(X,Y).
travel(X,Y,go(byTrain(X,Y))):-byTrain(X,Y).
travel(X,Y,go(byPlane(X,Y))):-byPlane(X,Y).
travel(X,Z,go(byCar(X,Y),T)):-byCar(X,Y),travel(Y,Z,T).
travel(X,Z,go(byTrain(X,Y),T)):-byTrain(X,Y),travel(Y,Z,T).
travel(X,Z,go(byPlane(X,Y),T)):-byPlane(X,Y),travel(Y,Z,T).
It seems to work...
?- travel(valmont, losAngeles, X).
X = go(byCar(valmont, saarbruecken), go(byTrain(saarbruecken, paris), go(byPlane(paris, losAngeles)))) ;
X = go(byCar(valmont, metz), go(byTrain(metz, paris), go(byPlane(paris, losAngeles)))) ;
false.
...but it hurts my eyes; all that repetition is a cry for abstraction.
I tried to eliminate the repetition by defining
oneLeg(X,Y):-byCar(X,Y);byTrain(X,Y);byPlane(X,Y).
...and redefining travel/3
as
travel(X,Y,go(oneLeg(X,Y))):-oneLeg(X,Y).
travel(X,Z,go(oneLeg(X,Y),T)):-oneLeg(X,Y),travel(Y,Z,T).
...but the results are not quite there yet:
?- travel(valmont, losAngeles, X).
X = go(oneLeg(valmont, saarbruecken), go(oneLeg(saarbruecken, paris), go(oneLeg(paris, losAngeles)))) ;
X = go(oneLeg(valmont, metz), go(oneLeg(metz, paris), go(oneLeg(paris, losAngeles)))) ;
false.
How can I force the replacement of instances of oneLeg
in the result with the specific byCar
, byTrain
, or byPlane
that "justifies" the oneLeg
instance?