Skip to main content

Types and signatures

Jazz infers the type of each expression. An explicit signature documents and constrains that result; the program is rejected when the implementation cannot satisfy it. Type variables allow one definition to work uniformly across several concrete types, while capability constraints require specific operations from those types.

Numeric operations normally require one concrete width; Int and Float are the default-width aliases. The only implicit mixed-domain rule is the direct built-in integral-to-Float or Float64 exception. It does not widen to Float16 or Float32, combine concrete float widths, or apply to user-defined operators. Use the target-named conversion functions for every other width change. Runtime values lists the built-in types and their exact promotion behavior.

Named types can carry type parameters:

Fragment:

data Box a = Box a.
extract :: Box(Int) -> Int.

This signature requires equality for its element type, while identity is unconstrained:

Fragment:

contains :: @{Eq(a)}: [a] -> a -> Bool.

identity :: a -> a.
identity = \(item) -> item.
identity @Int 1.

Explicit type application can select a type when inference does not have enough context, as identity @Int 1 does above. See capabilities for the current constraint and dispatch model, and the expression grammar for exact type syntax.