Thursday, February 19, 2009

Adventures in Prolog - Computations with lists II

As mentioned in my last post, this post is concerned with building some abstraction when computing with lists. For this, I will abstract the the addList and mulList prodecures into one more general processList procedure. processList will iterate over a list and process it according to some user-defined function. Users of F# might recognize this from F#'s map function offered by a list object.

At first we define the processList function. processList takes 4 input parameters - a list, a processing function some identity element and the result. processList processes some input list according to the provided processing function. The identity Identity element is used to process the empty list. The result of this operation is placed into the variable Res
.

%processList/4
processList([], F, Identity, Identity) :- functor(_, F, 3).
processList([HT], F, Identity, Res) :-
functor(_, F, 2),
processList(T, F, Identity, L1),
apply(F, [H, L1, Res]).

The functor procedure checks whether the user supplied processing function F is indeed a function accepting 3 Variables (F/3). processList is similar to mulList or addList, in that it uses the recursive definition of a list to process each list element. apply is used to call the user-supplied procedure F with submitted input variables.

By itself processList does not do much, it is merely the skeleton to enable abstract computation on lists. To make use of it, we have to define some processing function F.
As mentioned, I want to use processList to abstract addList and mulList. For this, let's define two ternary relations add and mul. add is used to realize addList and mul is given to realize mulList. Their definition is straightforward and presented in the following.

%test ops
add(X, 0, X).
add(0, _, 0).
add(X, Y, Z) :- Z is X + Y.

mul(_, 0, 0).
mul(0, _, 0).
mul(X, 1, X).
mul(1, X, X).
mul(X, Y, Z) :- Z is X*Y.

Given the above definitions, we may ask Prolog now:
?- processList([1, 2, 3, 4, 5], add, 0, R).
, which yields:
R = 15

Clearly, add and mul are simple examples but more powerful processing functions can be implemented and passed to processList.

No comments: