Gleam Data Types
Every value in Gleam has a type. The type tells Gleam what kind of data you are working with and what operations you can perform on it. Gleam checks types at compile time, so type mismatches never crash your running program.
The Basic Types
Gleam Primitive Types Overview
──────────────────────────────────────────────────
Type │ Example Values │ Use For
────────┼─────────────────────────┼───────────────────
Int │ 0, 42, -7, 1_000_000 │ Whole numbers
Float │ 3.14, -0.5, 1.0 │ Decimal numbers
String │ "hello", "Gleam" │ Text
Bool │ True, False │ Yes/No logic
Nil │ Nil │ "Nothing" / empty
Int — Whole Numbers
The Int type stores whole numbers without a decimal point. Gleam integers have no size limit — they grow as large as your computation needs.
let items = 5
let year = 2024
let temperature = -10
let population = 1_400_000_000 // underscore separates digits for readability
The underscore in 1_400_000_000 is just for readability. Gleam ignores it — the value is still one billion four hundred million.
Integer Literals in Other Bases
let hex = 0xFF // hexadecimal = 255
let octal = 0o77 // octal = 63
let binary = 0b1010 // binary = 10
Float — Decimal Numbers
The Float type stores numbers with a decimal point. A Float must always include the decimal point — even for whole values.
let price = 19.99
let gravity = 9.8
let ratio = 0.5
let big = 1.0e6 // scientific notation = 1,000,000.0Int vs Float: A Key Distinction
Int and Float do NOT mix automatically
──────────────────────────────────────────────────
let a: Int = 5
let b: Float = 2.0
// ✗ This is a compile error:
let result = a + b
// ✓ Convert first, then add:
let result = int.to_float(a) +. b
Gleam uses different operators for Int and Float arithmetic: + for Int, +. for Float. This prevents accidental precision loss.
String — Text
A String holds any sequence of text enclosed in double quotes. Gleam strings are UTF-8 encoded, so they support any language or emoji.
let greeting = "Hello"
let city = "東京" // Japanese — UTF-8 supported
let emoji = "🎉"
let empty = ""Multi-Line Strings
let poem = "Roses are red,
Violets are blue,
Gleam is typed,
Through and through."String Escape Sequences
Escape │ Meaning
────────┼──────────────────
\" │ Double quote
\\ │ Backslash
\n │ New line
\t │ Tab
\r │ Carriage return
String Concatenation
let first = "Gleam"
let last = "Lang"
let full = first <> " " <> last // "Gleam Lang"Bool — True or False
A Bool holds exactly one of two values: True or False. Note the capital letter — unlike many languages, Gleam's booleans start with uppercase.
let is_logged_in = True
let has_error = False
let can_proceed = TrueBool Operations
let a = True
let b = False
let both = a && b // AND → False
let either = a || b // OR → True
let flipped = !a // NOT → False
AND / OR Truth Table
──────────────────────────────────────────────
A │ B │ A && B │ A || B
──────┼───────┼────────┼────────
True │ True │ True │ True
True │ False │ False │ True
False │ True │ False │ True
False │ False │ False │ False
Nil — The Empty Value
Nil represents "nothing" in Gleam. It is different from other types — you use it when a function genuinely returns no meaningful result.
import gleam/io
pub fn print_hello() -> Nil {
io.println("Hello")
}
Functions that only produce side effects (like printing) return Nil. Think of it like a receipt that says "done" but contains no data.
Gleam does not use Nil to mean "missing value." For optional values, Gleam uses the Option type — covered in a later topic.
Type Checking in Action
What the Compiler Catches
──────────────────────────────────────────────
let name: String = "Riya"
let age: Int = "twenty-five" // ✗ COMPILE ERROR
// Expected: Int
// Found: String
let price: Float = 10 // ✗ COMPILE ERROR
// Expected: Float
// Found: Int (use 10.0)
Type Annotations
You can annotate any variable with its type using a colon:
let score: Int = 98
let name: String = "Asha"
let active: Bool = True
let value: Float = 3.14Annotations are optional for local variables — Gleam infers the type from the assigned value. Annotations become more important in function signatures, where they document the function's contract clearly.
Converting Between Types
Gleam does not perform automatic type conversion. You convert explicitly using standard library functions:
Type Conversion Functions
──────────────────────────────────────────────────
Convert From │ Convert To │ Function
─────────────┼────────────┼──────────────────────
Int │ Float │ int.to_float(n)
Float │ Int │ float.truncate(f)
Int │ String │ int.to_string(n)
Float │ String │ float.to_string(f)
String │ Int │ int.parse(s)
String │ Float │ float.parse(s)
import gleam/int
import gleam/float
let n = 42
let f = int.to_float(n) // 42.0
let s = int.to_string(n) // "42"
let x = 3.7
let i = float.truncate(x) // 3 (drops the decimal)
Comparing Values
Use comparison operators to compare values of the same type:
Comparison Operators
──────────────────────────────────────────────
Operator │ Meaning │ Returns
─────────┼──────────────────────┼────────
== │ Equal │ Bool
!= │ Not equal │ Bool
< │ Less than │ Bool
> │ Greater than │ Bool
<= │ Less than or equal │ Bool
>= │ Greater than or equal│ Bool
let a = 10
let b = 20
let result = a < b // TrueGleam does not allow comparisons across types. You cannot compare an Int to a String — the compiler stops you before that mistake reaches production.
Practical Example
import gleam/io
import gleam/int
pub fn describe_age(age: Int) -> String {
let category =
case age < 18 {
True -> "minor"
False -> "adult"
}
"Age " <> int.to_string(age) <> " is a " <> category
}
pub fn main() {
io.println(describe_age(16)) // Age 16 is a minor
io.println(describe_age(30)) // Age 30 is an adult
}
This example combines Int, Bool, and String types with a conversion function. Each type does exactly one job — counting, deciding, and displaying.
