Gleam Modules
A module is a single .gleam file. It groups related functions, types, and constants into one named unit. Modules control what is visible to other parts of your codebase, enabling clean separation of concerns and preventing unintended dependencies.
Modules Are Files
One file = One module
──────────────────────────────────────────────────
src/user.gleam → module: user
src/order.gleam → module: order
src/utils/format.gleam → module: utils/format
The module name is the file path relative to src/, with .gleam removed and slashes kept as separators. No registration, no declaration — the file name is the module name.
Public vs Private
// src/math.gleam
pub fn add(a: Int, b: Int) -> Int {
a + b
}
pub fn multiply(a: Int, b: Int) -> Int {
a * b
}
fn helper(x: Int) -> Int { // No pub — private to this module
x * x
}
Visibility Rules
──────────────────────────────────────────────────
pub fn → visible anywhere (other modules, tests)
fn → visible only inside this file
pub type → type visible to importers
type → type internal to this module only
pub const → constant visible to importers
const → constant internal to this module
Public Types
// src/product.gleam
pub type Product {
Product(
id: Int,
name: String,
price: Float
)
}
pub fn create(id: Int, name: String, price: Float) -> Product {
Product(id: id, name: name, price: price)
}
fn validate_price(price: Float) -> Bool {
price >. 0.0
}
Opaque Types
Mark a type as pub opaque to export the type name but hide its internal structure. Callers can use the type but cannot construct or destructure values directly:
// src/token.gleam
pub opaque type Token {
Token(value: String, expires_at: Int)
}
pub fn create_token(user_id: Int) -> Token {
Token(value: generate_value(user_id), expires_at: now() + 3600)
}
pub fn is_valid(token: Token) -> Bool {
now() < token.expires_at
}
Opaque Type Access
──────────────────────────────────────────────────
From token.gleam:
Can create Token(value: ..., expires_at: ...) ✓
Can read token.value ✓
From other modules:
Can use Token as a type ✓
Can call create_token, is_valid ✓
CANNOT do: Token(value: ...) directly ✗
CANNOT do: token.value ✗
Module Constants
// src/config.gleam
pub const max_retries = 3
pub const default_timeout = 5000
pub const app_version = "1.0.0"
const internal_secret = "not exported"
Organizing Multiple Functions
// src/currency.gleam
pub type Currency { INR; USD; EUR; GBP }
pub fn symbol(c: Currency) -> String {
case c { INR -> "₹"; USD -> "$"; EUR -> "€"; GBP -> "£" }
}
pub fn format_amount(amount: Float, currency: Currency) -> String {
symbol(currency) <> float.to_string(amount)
}
pub fn convert(amount: Float, from: Currency, to: Currency) -> Float {
let usd = to_usd(amount, from)
from_usd(usd, to)
}
fn to_usd(amount: Float, from: Currency) -> Float {
case from {
INR -> amount /. 83.0
USD -> amount
EUR -> amount *. 1.08
GBP -> amount *. 1.27
}
}
fn from_usd(amount: Float, to: Currency) -> Float {
case to {
INR -> amount *. 83.0
USD -> amount
EUR -> amount /. 1.08
GBP -> amount /. 1.27
}
}
Private helper functions to_usd and from_usd do the detailed work. The public convert function exposes a clean interface. Callers never need to know about the internal USD conversion step.
The Module Boundary
Module Boundary Diagram
──────────────────────────────────────────────────
currency module
┌─────────────────────────────────────┐
│ PUBLIC interface │
│ ┌──────────┐ ┌────────────────┐ │
│ │ symbol() │ │ format_amount()│ │
│ │ convert()│ └────────────────┘ │
│ └──────────┘ │
│ │
│ PRIVATE internals │
│ ┌──────────┐ ┌────────────────┐ │
│ │ to_usd() │ │ from_usd() │ │
│ └──────────┘ └────────────────┘ │
└─────────────────────────────────────┘
↑ other modules see only the public interface
Key Points
Module Essentials
──────────────────────────────────────────────────
1. One file = one module; name = file path from src/
2. pub exposes functions, types, and constants
3. No pub = private to this file only
4. pub opaque hides internal structure of a type
5. Modules enforce separation — callers depend only
on the public interface, not the implementation
6. No module declaration needed — the file IS the module
Modules are Gleam's primary unit of organization. A well-designed module hides complexity behind a clear public interface, making the rest of the codebase easier to read, test, and change.
