Type and mode declarations for compiler-generated field access functions for fields of constructors local to a module may be placed in the interface section of the module. The user-supplied declarations will be used instead of any automatically generated declarations. This allows the implementation of a type to be hidden while still allowing client modules to use record syntax to manipulate values of the type. Supplying a type declaration and a single mode declaration also allows higher-order terms to be created from a field access function without using explicit lambda expressions.
Declarations for field access functions for fields occurring in the interface section of a module must also occur in the interface section.
If there are multiple fields with the same label in the same module, only one of those fields can have user-supplied declarations for its selection function. Similarly, only one of those fields can have user-supplied declarations for its update function.
Declarations and clauses for field access functions can also be supplied for fields which are not a part of any type. This is useful when the data structures of a program change so that a value which was previously stored as part of a type is now computed each time it is requested. It also allows record syntax to be used for type class methods.
User-declared field access functions may take extra arguments.
For example, the Mercury standard library module
contains the following functions:
:- func elem(K, map(K, V)) = V is semidet. :- func 'elem :='(K, map(K, V), V) = map(K, V).
Field access syntax may be used
at the top-level of
and in the head of clauses.
:- func map(K, V) ^ elem(K) = V. :- mode in ^ in = out is semidet. Map ^ elem(Key) = map.lookup(Map, Key). :- func (map(K, V) ^ elem(K) := V) = V. :- mode (in ^ in := in) = out is semidet. (Map ^ elem(Key) := Value) = map.set(Map, Key, Value).
The Mercury standard library modules
define similar functions.