Type and effect systems can be seen as an extension of classical type systems known from functional languages (see [19] for a detailed description). The basic idea is to extend the type annotation for a function with an effect that may occur during the application of this function. For every expression a type and the effect of its reduction can be approximated. Type and effect systems provide for powerful analyses like exception analysis [21], side effect or communication analysis [19, 20]. They can be used to extend classical type systems but also work on any kind of type domain. For instance, they can be applied to imperative languages, too, if one takes the set of states as type domain [19].
Since in Curry nondeterminism is mostly caused by uninstantiated variables in arguments of functions that are evaluated by narrowing, we use a type system to distinguish between ground terms and any terms. Thus, we define the type expressions as follows:

G denotes a ground term, A denotes any term. Of course, a ground term
is also any term, so we have subtyping [2],
i.e.,
.
just
means that any term of type
has also type
. A common example
for this is
because every natural number is also an integer.
For functions it is important to notice that covariance holds for the
result type but contravariance for the argument types, i.e.,
iff
.
This is easy to understand if we think of smaller types as more precise
information. The type
is smaller than
and it
is more precise, because it provides information about a larger
set of inputs. Thus, the
larger the input type, the more precise the information, i.e., the smaller the
function type. The opposite holds for the output type, i.e.,
is
smaller than
, because the information about the target set
is more precise.
Our type system allows several types for one expression. For instance, for a function defined by