This document discusses the list_utils module and the predicates exported from this module. Generally, lists can be considered to be the fundamental, essential, non-atomic data type, and, as such, a body of standard functionality has grown to be canon around this data type. This module implements the most-used functionality from that canon and presents it to the Prolog user as one protocol.
This module follows the pattern of list-manipulation taken by the functional programming community, which is to use "functionals" (constructed functions passed in as arguments) to transform the list from its original state to another (possibly resulting in an object that is not a list) state. Given this, it is necessary to understand how to construct a functional that does the work necessary to transform the list into the state desired: both the combinators and the lambda modules provide protocols to construct functionals.
One must also consider the non-functional approach to exhaustive list-processing: this module for the most part takes the exhaustive approach as the way to perform list-processing, but there are other approaches that better fits the situation at hand, particularly for Prolog. In cases where non-determinism or choice is more important than a comprehesive scan, then operators from the syntax module are more appropriate, particularly ones that select a member or use (reverse- or bi-directional-) implication to narrow a search. This module follows the functional, comprehesive, approach to list-processing, so use this module when the entire list must be transformed; look elsewhere (such as transforming the list into a set or bag and then operating on the new data type) when logic or selection is desireable.
The following set of canonical functions have not been implemented in this module. When the need arises for any of these functions, they will be added as necessary. These functions are part of the canon, so their functionality is defined in a variety of sources.1
zip(+ListA, +ListB, ?List) List is the result of alternating the elements of ListA and ListB, starting with the first element of ListA (followed by the first element of ListB, then the second element of listA, then the second element of ListB, etc.). When there are no more elements remaining in one of the lists, the remainder of the nonempty list is appended.foldr(+Pred, +List, +Accum, ?Ans) The same functionality offoldl/4, except that the List is folded starting from the last element (the right of the list) instead of the first.replicate(+Integer, +Seed, ?List) List is Seed repeated Integer times.unfold/5is a generalization of this predicate.The following predicates assume normal order ("lazy") evaluation as they give infinite results. We would need to build in a facility for Prolog to evalute the results incrementally ("lazily") in order to be able to implement these predicates. iterate(+Pred, +Seed, -List) Gives an infinite List from repeated successive application of Pred to Seed.List = [Seed, Pred(Seed), Pred(Pred(Seed)), ...].repeat(+Seed, -List) Gives an infinite List from repeating Seed infinitely. The same asList = [Seed|List].cycle(+List, ?Circle) Takes a (possibly cyclic (infinitely repeating)) list and makes it cyclic:Circle = List ++ Circle.
:- use_module(library(lambda), [apply/3, test/2]).
:- use_module(library(peano), [peano/2]).
:- use_module(library(combinators), [phi_equivalent/2, compose/3]).
:- use_module(library(syntax), [try/3]).
The list_utils module exports the following predicates:
This module exports no operators.
| Synopsis: | map_reversed(+Functor, +List, +DCGIn, -DCGOut) | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Arguments: |
|
||||||||||||
| Description: | Recursively applies
Functor to the
elements of
List,
prepending the result onto
DCGIn. In short,
| ||||||||||||
| Backtracking: | Standard. N.B.: one cannot use the trick of having DCGIn free and DCGOut bound to the initial state in the hope of obtaining a transformed result in DCGIn in the element ordering of List: this predicate fails for that case. Use map/3 if element ordering should be preserved. | ||||||||||||
| Example: | Here we demonstrate accumulating a set of similarly operating rules (specifically, a set of rules that take no parameters) onto a set of rules with parameters already assigned for testing by a unit test framework: | ||||||||||||
| See also: | map/3, reverse/2 |
| Synopsis: | map(+Functor, +ListIn, ?ListOut) | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Arguments: |
|
|||||||||
| Description: | Recursively applies
Functor to the
elements of ListIn,
resulting in ListOut
containing the tranformed elements with the same
ordering as ListIn. The
research from the functional programming language community
has shown that all (list-)transformation functions are
derivatives of | |||||||||
| Backtracking: | If ListOut is free,
deterministic; otherwise, semideterministic based on the
unification of the | |||||||||
| Examples: | In this example, we have a party (HiLo) that we pair with a each party in an input list:
This next example continues from the result of the
map(lambda(rule(ID, Params, Period), nominal(no_rule(ID, reason(zero_score_rule), InnocuousData, Duration, Params, Period, InitEnv))), NoScoreConstructs, NoScoreNoRules) Incidentally, we see from this example that the input variable of a lambda-term can be destructured just as any other Prolog unification. | |||||||||
| See also: | |
| Synopsis: | filter(+List, +Match, ?Trues, ?Fails) | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Arguments: |
|
||||||||||||
| Description: | Converts List into two
lists, one that has elements that match
Match and the other
with the elements that do not. | ||||||||||||
| Backtracking: | If Trues and
Fails are free,
deterministic; otherwise, semideterministic based on the
unifications of the | ||||||||||||
| Examples: | In this example, we create Match that is a unification term discriminator, filtering a set of rules into ones with at least one parameter and ones with none:
This next example uses a psi/2-term to filter a list based on a predicate:
The result of the above call is that | ||||||||||||
| See also: | |
| Synopsis: | foldl(+List, +BinaryFunctor, +Seed, ?Ans) | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Arguments: |
|
||||||||||||||||||||||||||||||||||||
| Description: | This is the fundamental (program) transformation function,
given to us by research into functional
programming.2
This predicate takes the elements of a list and an initial value
and recursively applies
BinaryFunctor
to the two obtaining a final result (which, only in the special
case of the secondary function of the composition being
concatenation does a list result, otherwise the result is a
non-list term).
| ||||||||||||||||||||||||||||||||||||
| Backtracking: | depends on the modality of Ans
and BinaryFunctor
(e.g. if Ans is free and
BinaryFunctor is
deterministic, then this instance of | ||||||||||||||||||||||||||||||||||||
| Examples: | Here is a simple definition of
Here is a program that multiplies ratios, given a fixed denominator:
So, for example, let's say a Bayesian system has collect counts over seven attribute for 595 occurrences of a class, if the counts of a new input matched the following:
then | ||||||||||||||||||||||||||||||||||||
| See also: | The dual of | ||||||||||||||||||||||||||||||||||||
| Synopsis: | unfold(+StopPred, +CurrPred, +NextPred, +Seed, ?Ans) | |||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Arguments: |
|
|||||||||||||||
| Description: | This predicate serves the need of obtaining a list from a starting value and a termination test. In essence, this is the mathematical, or functional, definition of a series.5 This predicate implicitly builds a list instead of requiring the programmer to explicitly enumerate the elements (by defining the list by hand or by creating and calling a recursive predicate). | |||||||||||||||
| Backtracking: | Nondeterministic; choice-points are left at each inductive call in the construction of Ans. | |||||||||||||||
| Examples: | The set_utils module defines the arithmetic sequence operator thusly:
It may be a fruitful line of research, given
monadic
tranformations6
to allow | |||||||||||||||
| See also: | |
| 1 | For example, The appendix with the prelude definition of Haskell in the appendix of [Dav1992], or the Haskell manual itself (in the Standard Prelude section), obtainable from http://haskell.org/onlinereport/standard-prelude.html, or, from the source we use, the Mercury library reference manual, particularly the list module section, available from http://cs.mu.oz.au/research/mercury. |
| 2 | Because
... in the functional programming community. We have a different signature for this module. Deal with it. |
| 3 | The programming language Dylan names this
function |
| 4 | I placed all the caveats to
describe |
| 5 | Of course, series, and their construction, has been the study of mathematical philosophers since ancient times. The serious study of series have entered into the computer science field with the adoption of the series type into Common Lisp (see, e.g., [Wat89], or the Series appendix of [Ste84]), further refined by the list construction syntax in the Haskell programming language (see, particularly, §3.10 and §3.11 of [Jon2002]). |
| 6 | A good collection of essays on monads can be found at http://haskell.cs.yal.edu/bookshelf/#monads. Unfortunately, the link to the excellent, practical, introductory article: "What the hell are Monads?" no longer functions. |
| [Dav1992] | An Introduction to Functional Programming Using Haskell, A. J. T. Davie, Cambridge Computer Science Texts, UK, 1992. |
| [Jon2002] | Haskell 98 Language and Libraries, the Revised Report, Simon Peyton Jones, ed., et al, http://www.haskell.org/onlinereport, December 2002. |
| [Ste1984] | Common Lisp: the Language, 2nd ed., Guy L. Steel, Jr., Digital Press, 1984. |
| [Wat1989] | Richard C. Waters, "Optimization of Series Expression: Part II: Overview of the Theory and Implementation", A.I. Memo No. 1083, Massachusetts Institute of Technology, Artificial Intelligence Laboratory, December 1989. |
| Author: | Douglas M. Auclair |
| Created: | October 14, 2005 |
| Last Modified: | October 17, 2005 |