7.3 Type Declarations of User-Defined Types

As seen, the basic syntax of a type is an atom followed by closed parentheses. New types are declared using -type and -opaque attributes as in the following:

  1. -type my_struct_type() :: Type.
  2. -opaque my_opaq_type() :: Type.

The type name is the atom my_struct_type, followed by parentheses. Type is a type as defined in the previous section. A current restriction is that Type can contain only predefined types, or user-defined types which are either of the following:

  • Module-local type, that is, with a definition that is present in the code of the module
  • Remote type, that is, type defined in, and exported by, other modules; more about this soon.For module-local types, the restriction that their definition exists in the module is enforced by the compiler and results in a compilation error. (A similar restriction currently exists for records.)

    Type declarations can also be parameterized by including type variables between the parentheses. The syntax of type variables is the same as Erlang variables, that is, starts with an upper-case letter. Naturally, these variables can - and is to - appear on the RHS of the definition. A concrete example follows:

  1. -type orddict(Key, Val) :: [{Key, Val}].

A module can export some types to declare that other modules are allowed to refer to them as remote types. This declaration has the following form:

  1. -export_type([T1/A1, ..., Tk/Ak]).

Here the Ti's are atoms (the name of the type) and the Ai's are their arguments

Example:

  1. -export_type([my_struct_type/0, orddict/2]).

Assuming that these types are exported from module 'mod', you can refer to them from other modules using remote type expressions like the following:

  1. mod:my_struct_type()
  2. mod:orddict(atom(), term())

It is not allowed to refer to types that are not declared as exported.

Types declared as opaque represent sets of terms whose structure is not supposed to be visible from outside of their defining module. That is, only the module defining them is allowed to depend on their term structure. Consequently, such types do not make much sense as module local - module local types are not accessible by other modules anyway - and is always to be exported.