Skip to main content
Algebraic datatypes (ADTs) allow you to define structured data types similar to enums, structs, and recursive types in programming languages. Z3 supports constructors, accessors, and recognizers for datatypes.

Simple Datatypes

Enumeration Types

Create simple enumerations:
C API: Z3_mk_enumeration_sort(c, name, n, enum_names, enum_consts, enum_testers) (api_datatype.cpp:88)

Tuple Types

Create product types (tuples):
C API: Z3_mk_tuple_sort(c, name, num_fields, field_names, field_sorts, mk_tuple_decl, proj_decls) (api_datatype.cpp:26)

Recursive Datatypes

List Type

Define recursive list structures:
C API: Z3_mk_list_sort(c, name, elem_sort, nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl) (api_datatype.cpp:157)

Tree Type

Define binary trees:

Constructor Operations

Define Constructors

C API: Z3_mk_constructor(c, name, tester, num_fields, field_names, sorts, sort_refs) (api_datatype.cpp:220)

Recognizers (Type Tests)

Test which constructor was used:
C API: Recognizers are created automatically with each constructor

Accessors (Field Access)

Access fields of constructed values:
C API: Accessors are retrieved via Z3_query_constructor (api_datatype.cpp:259)

Mutually Recursive Datatypes

Define multiple datatypes that reference each other:
C API: Z3_mk_datatypes(c, num_sorts, sort_names, sorts, constructor_lists) (api_datatype.cpp:456)

Polymorphic Datatypes

Create datatypes parameterized by type variables:
C API: Z3_mk_polymorphic_datatype(c, name, num_parameters, parameters, num_constructors, constructors) (api_datatype.cpp:378)

Update Operations

Update fields of datatype values:
C API: Z3_datatype_update_field(c, f, t, v) (api_datatype.cpp:669)

Query Functions

Get information about datatypes:
C API:
  • Z3_is_recursive_datatype_sort(c, t) (api_datatype.cpp:498)
  • Z3_get_datatype_sort_num_constructors(c, t) (api_datatype.cpp:508)
  • Z3_get_datatype_sort_constructor(c, t, idx) (api_datatype.cpp:543)
  • Z3_get_datatype_sort_recognizer(c, t, idx) (api_datatype.cpp:552)
  • Z3_get_datatype_sort_constructor_accessor(c, t, idx_c, idx_a) (api_datatype.cpp:575)

Complete Examples

Example 1: Expression Tree

Example 2: Option Type (Maybe)

Example 3: JSON-like Structure

Example 4: State Machine

Pattern Matching

Use recognizers and accessors to implement pattern matching:

Theory Features

  • Constructors are injective: Different arguments produce different values
  • Constructors are disjoint: Values from different constructors are always distinct
  • Acyclic constraint: Prevents infinite values in recursive types
  • Exhaustive: Every value is constructed by exactly one constructor

Implementation Notes

  • Datatypes compile to uninterpreted functions with axioms
  • Recognizers enforce constructor disjointness
  • Accessors are only valid after recognizer check
  • Recursive types require special encoding to ensure termination

References

  • Implementation: src/api/api_datatype.cpp
  • Theory plugin: src/ast/datatype_decl_plugin.h