The unit Type
The unit type represents the absence of a meaningful value while still being a real, first-class type. It is similar to void in other languages, but with an explicit value.
Unlike None (the null value), unit:
- Has its own distinct runtime value (printed as
unit) - Is not the same as
None/null - Is intended for APIs that conceptually "return nothing" but still participate in the type system
Quick Overview
- Type name:
unit - Value: a single value, printed as
unit - Equality:
unit == unit→trueunit != unit→falseNone == unit→false- Truthiness:
unitis treated as falsy, similar toNone.
| Basic unit usage | |
|---|---|
When to Use unit vs None
Harneet distinguishes between unit and None:
unit- A proper type with a single inhabitant
- Used for functions that conceptually return no data
- Plays well with the type system (e.g. generics / APIs that want an explicit "no payload" type)
None- A value representing null / no value
- Commonly used in error handling patterns as the "no error" sentinel
Example: Side-effecting functions
| Functions returning unit | |
|---|---|
Example: Distinguishing None and unit
Equality Semantics
The == / != operators for unit follow these rules:
- All
unitvalues are equal to each other unitis never equal to values of other types (includingNone)
This mirrors how None behaves (all None values are equal to each other, but not to other types), while keeping the two concepts distinct.
Truthiness in Conditionals
unit is considered falsy:
| unit truthiness | |
|---|---|
This matches the intuition that a unit result carries no useful data.
Zero Values
The zero value of unit is the unit value itself:
Variables of type unit are always in a valid state; there is no "uninitialized" or "null" unit.
Patterns & Best Practices
Using unit in function return types
When you declare a function to return unit, you are making an explicit API promise: this function performs work but does not return a meaningful value.
For such functions:
- A naked
returnis allowed and treated as returningunit. - Falling off the end of the function body (no
returnat all) is also treated as returningunit. - Any
returnwith a value is a type error.
This applies consistently to:
- Named functions
- Anonymous functions
- Arrow functions (both block and expression bodies)
| unit-returning functions | |
|---|---|
Choosing between unit and None
- Use
unitwhen you want to say "this API returns no payload" but still participate in the type system (e.g. generics, explicit contracts). - Use
Noneas a value when you need a nullable sentinel, especially in error-handling patterns (e.g.(T, error)whereerrorisNoneon success). - Leave the return type unspecified (
function f() { ... }) only when you intentionally want a loosely-typed,None-returning function for scripting-style code.
In short:
- Structured APIs / libraries → prefer
unitfor no-result functions. - Error channels and sentinels → use
Noneas the "no error" value.
Design Notes
unitis not an alias forNoneornull.- There is a dedicated runtime object for
unit, separate from theNonevalue. - The interpreter and VM both agree on:
- A single logical
unitvalue - Equality and truthiness semantics described above.
Use unit when you want your APIs and types to clearly say: this returns no data, while still staying inside Harneet's strong, explicit type system.