types
This library implements predicates over standard Prolog term types and also terms representing common data structures such as lists and pairs.
It also includes a user-extensible type
object defining type
checking predicates over common Logtalk and Prolog term types. The types
define a hierarchy with the Prolog type term
at the root (i.e.
type-checking a predicate argument of type term
trivially succeeds).
Some types are only meaningful for backend Prolog systems supporting
non-universal features (e.g. cyclic
or char(CharSet)
with a
Unicode character set). See the API documentation for a full list of the
types defined by default.
API documentation
Open the ../../docs/library_index.html#types link in a web browser.
Loading
To load all entities in this library, load the loader.lgt
file:
| ?- logtalk_load(types(loader)).
In case your code only requires the most basic types, you can load in alternative the file:
| ?- logtalk_load(basic_types(loader)).
See the notes on the basic_types
virtual library for details.
Testing
To test this library predicates, load the tester.lgt
file:
| ?- logtalk_load(types(tester)).
Type-checking
This library type
object can be used to type-check common Logtalk
and Prolog term types (see the object documentation for a listing of all
the pre-defined types). The valid/2
predicate succeeds or fails if a
term is of a given type. For example:
| ?- type::valid(positive_integer, 42).
yes
| ?- type::valid(positive_integer, -13).
no
The check/2
and check/3
predicates throw an exception if a term
is not of a given type. For example:
| ?- catch(type::check(integer, abc), Error, true).
Error = type_error(integer, abc)
yes
If we require a standard error/2
exception term, the check/3
predicate takes a context argument. For example:
| ?- catch(type::check(integer, abc, foo/3), Error, true).
Error = error(type_error(integer, abc), foo/3)
yes
Typically, the context is provided by calling the built-in context/1
method.
Defining new types
To define a custom type, define clauses for the multifile predicates
type::type/1
(to declare the type) and type::check/2
(to
type-check values). For example:
:- multifile(type::type/1).
type::type(age).
:- multifile(type::check/2).
type::check(age, Term) :-
type::check(between(non_negative_integer, 0, 150), Term).
Be careful to ensure that new type definitions don’t introduce spurious
choice-points for these predicates. The unit tests of the types
library perform this check for pre-defined and loaded user-defined
ground types.
When defining a meta-type (i.e. a type with arguments that are also
types), add also a clause for the type::meta_type/3
multifile
predicate. For example:
:- multifile(type::meta_type/3).
type::meta_type(tuple(Type1, Type2, Type3), [Type1, Type2, Type3], []).
This predicate is called when checking if a type is a defined type. For meta-types, that check must extend to the sub-types.
Examples
See e.g. the os
library implementation of custom types for files and
directories. Or the expecteds
and optionals
libraries custom
types. See also the my_types
programming example.