# Data types

There are two subsets of data types that each datatype will fall into; fundamental and compound.

A fundamental type is a data type which is defined in the core language. This is not specific to Noir. Examples in modern programming languages such as Rust are u32, usize and char.

A compound type is a type in the core language which must be defined using another type. Examples in modern programming languages are arrays, tuples and functions.

Although each value in a constraint system is fundamentally a field element, we add a layer of abstraction over this; each value can be concealed or revealed.

A concealed value is known only to the Prover, while, a revealed value is known by the Prover and Verifier. All concealed and revealed values are fundamental types.

## Fundamental Types

### Concealed Types

Concealed types are generally referred to as witnesses.

#### Witness Type

A Witness type is the default concealed type. Here's an example that shows declaration and usage of the Witness type.

fn main(x : Field, y : Field) {
priv z = x + y;
}

x, y and z are Witness types. Using the priv keyword we derived a new Witness type z which is constrained to be equal to x + y.

#### Integer Type

An integer type is a witness type which has been constrained using a range constraint. The Noir front-end currently supports arbitrary sized integer types.

Below we show the integer type in action:

fn main(x : Field) {
priv y = x as u24;
}

x and y are both concealed types, however y is an integer type. If y exceeds the range $$[0,2^{24}-1]$$ then any proof created will output false by the verifier.

Note: The Aztec backend only supports even sized integer types currently, so while using the Aztec backend, only even sized integer types such as u32, u48 will produce proofs.

### Revealed Types

#### Constants

A constant type is a value that does not change per circuit instance. This is different to a concealed type which changes per proof. If a constant type that is being used in your program in changed, then your circuit will also change.

Below we show how to declare a constant value:

fn main() {
const a = 5;
}

#### Public Types

A public type is a value that may change per circuit instance. Unlike Constants, changing a public value will not change the circuit.

fn main(x : pub Field) {

}

As of the beta release, public types can only be declared through type parameters. In the code, they are treated no differently to witness types.

Note: This behaviour and type will change in future releases, to catch a linearity bug in user code.

## Compound Types

Compound types are declared using the let keyword. Currently arrays are the only supported compound type.

#### Arrays

An array is a data structure which allows you to group together data types. All values in an array must be of the same type; homogeneous.

fn main(x : Field, y : Field) {
let my_arr = [x, y];
}

Example: An array of Witness types cannot be grouped together with an array of Integer types.