This module defines the structures used by Swish to represent and
manipulate datatypes. It is designed as a basis for handling datatyped
RDF literals, but the functions in this module are more generic.

DatatypeVal is a structure that defines a number of functions
and values that characterize the behaviour of a datatype.

A datatype is specified with respect to (polymophic in) a given
type of (syntactic) expression with which it may be used, and
a value type (whose existence is hidden as an existential type
within DatatypeMap).

(I tried hiding the value type with an internal existential
declaration, but that wouldn't wash. Hence this two-part
structure with Datatype in which the internal detail
of the value type is hidden from users of the Datatype class.)

The datatype characteristic functions have two goals:

to support the general datatype entailment rules defined by
the RDF semantics specification, and

to define additional datatype-specific inference patterns by
means of which provide additional base functionality to
applications based on RDF inference.

Datatype-specific inferences are provided using the DatatypeRel
structure for a datatype, which allows a number of named relations
to be defined on datatype values, and provides mechanisms to
calculate missing values in a partially-specified member of
a relation.

Note that rules and variable binding modifiers that deal with
combined values of more than one datatype may be defined
separately. Definitions in this module are generally applicable
only when using a single datatype.

An alternative model for datatype value calculations is inspired
by that introduced by CWM for arithmetic operations, e.g.

(1 2 3) math:sum ?x => ?x rdf:value 6

(where the bare integer n here is shorthand for "n"^^xsd:integer).

Datatype-specific inference patterns are provided in two ways:

by variable binding modifiers that can be combined with the
query results during forward- for backward-chaining of
inference rules, and

by the definition of inference rulesets that involve
datatype values.

I believe the first method to be more flexible than the second,
in that it more readily supports forward and backward chaining,
but can be used only through the definition of new rules.

Type parameters:

ex

is the type of expression with which the datatype may be used.

vt

is the internal value type with which the labels are associated.

lb

is the type of label that may be used as a variable in an
expression or rule.

vn

is the type of node that may be used to carry a value in an
expression or rule.

a list of argument value predicates and
function descriptors. The predicate indicates any
additional constraints on argument values (e.g. the result
of abs must be positive). Use (const True) for the predicate
associated with unconstrained relation arguments.
For each argument, a list of function descriptors is
supplied corresponding to alternative values (e.g. a square
relation would offer two alternative values for the root.)

a function that takes an argument value predicate,
a function descriptor and applies it to a supplied argument
list to return:
Just a calculated list of one or more possible argument values,
Just [] indicating insufficient information provided, or
Nothing indicating inconsistent information provided.
May be one of unaryFnApp, binaryFnApp, listFnApp or
some other caller-supplied value.

Given a list of argument values and a list of functions for
calculating new values from supplied values, return a list
of argument values, or Nothing if the supplied values are
inconsistent with the calculations specified.

Each list of values returned corresponds to a set of values that
satisfy the relation, consistent with the values supplied.

Functions are described as tuple consisting of:

(a) a predicate that the argument is required to satisfy

(b) a function to apply,

(c) a function to apply function (b) to a list of arguments

(d) argument list index values to which the function is applied.

Each supplied argument is of the form Maybe a, where the argument
has value type a. Nothing indicates arguments of unknown value.

The basic idea is that, for each argument position in the relation,
a function may be supplied to calculate that argument's possible values
from some combination of the other arguments. The results calculated
in this way are compared with the original arguments provided:
if the values conflict then the relation is presumed to be
unsatisfiable with the supplied values, and Nothing is returned;
if there are any calculated values for arguments supplied without
any values, then tbe calculated values are used.
If there are any arguments for which no values are supplied or
calculated, then the relation is presumed to be underdetermined,
and Just [] is returned.

altArgs support for list functions (e.g. sum over list of args),
where first element of list is a fold over the rest of the list,
and remaining elements of list can be calculated in terms
of the result of the fold and the remaining elements

and the result of the folded function does not depend on
the order that the list elements are processed.

NOTE: the list of ListFnDescr values supplied to altArgs must
be at least as long as the argument list. In many cases, Haskell
lazy evaluation can be used to supply an arbitrarily long list.
See test cases in spike-altargs.hs for an example.

Each function accepts a list of values and returns a list of values.
The exact significance of the different values supplied and returned
depends on the variable binding pattern used (cf. ApplyModifier),
but in all cases an empty list returned means that the corresponding
inputs are not consistent with the function and cannot be used.

Type of function used to apply a data value modifier to specified
variables in a supplied variable binding. It also accepts the
name of the datatype modifier and carries it into the resulting
variable binding modifier.

(Note that vn is not necessarily the same as vt, the datatype value
type: the modifier functions may be lifted or otherwise adapted
to operate on some other type from which the raw data values are
extracted.)

ApplyModifier function for use with DatatypeMod in cases
when the value mapping is a 1->1 function and inverse, such
as negate.

nam

is the name from the DatatypeMod value that is carried into
the resulting variable binding modifier.

fns

are functions used to implement details of the variable
binding modifier:

is [x,y] -> [?], used as a filter (i.e. not creating any
new variable bindings), returning a non-empty list if x and y
are in the appropriate relationship.

is [y] -> [x], used to perform the calculation in a forward
direction.

is [x] -> [y], used to perform the calculation in a backward
direction. This may be the same as (2) (e.g. for negation)
or may be different (e.g. increment).

lbs

is a list of specific label values for which a variable binding
modifier will be generated. (The intent is that a variable-free
value can be generated as a Curried function, and instantiated
for particular variables as required.)

Note: an irrefutable pattern match for lbs is used so that a name
for the VarBindingModify value can be extracted using an undefined
label value.