Examples
On this page
These examples are drawn from the PAKT test suite. Each demonstrates a different aspect of the format with commentary.
Scalar Types
Every value in PAKT carries an explicit type. Here are all the scalar types:
greeting:str = 'hello world'
count:int = 42
hex:int = 0xFF
binary:int = 0b1010_0011
octal:int = 0o77
big:int = 1_000_000
negative:int = -273
price:dec = 19.99
avogadro:float = 6.022e23
active:bool = true
inactive:bool = false
id:uuid = 550e8400-e29b-41d4-a716-446655440000
started:date = 2026-06-01
updated:ts = 2026-06-01T14:30:00Z
payload:bin = x'48656C6C6F'
Key points:
- Integers support decimal, hex (
0x), binary (0b), and octal (0o) literals - Underscores (
_) are visual separators —1_000_000is the same as1000000 decis arbitrary-precision decimal;floatis IEEE 754 binary64binaccepts both hex (x'...') and base64 (b'...') forms- Timestamp values require a timezone (
Zor offset like-04:00)
String Varieties
Strings are always quoted. PAKT supports single quotes, double quotes, raw strings, escape sequences, and multi-line triple-quoted strings:
# Single and double quotes are interchangeable
single:str = 'hello world'
double:str = "hello world"
# Standard escape sequences
newline:str = 'line one\nline two'
tabbed:str = "col1\tcol2"
backslash:str = 'C:\\Users\\alice'
# Unicode escapes
bmp-escape:str = '\u2603' # snowman ☃
emoji:str = '😀' # literal UTF-8 for supplementary plane
# Raw strings
windows-path:str = r'C:\Users\alice\Documents'
pattern:str = r"^\d{3}-\d{4}$"
Multi-line strings
Triple quotes (''' or """) open a multi-line string. The first non-blank content line determines how much leading whitespace is stripped:
# Indentation stripping: the first content line has 4 leading spaces, so 4 are stripped from each non-blank content line
query:str = '''
SELECT id, name
FROM users
WHERE active = true
'''
# Result: "SELECT id, name\nFROM users\nWHERE active = true"
# No stripping when the first non-blank content line starts at column 0
raw:str = '''
no indent here
second line
'''
# Result: "no indent here\nsecond line"
# Double-quoted multi-line works the same way
poem:str = """
Roses are red,
Violets are blue,
PAKT is typed,
And so are you.
"""
# Raw multi-line strings keep backslashes literal
template:str = r'''
Hello \n World
'''
Atoms
Atoms are bareword identifiers constrained to a declared set. They’re similar to enums — the type declares the allowed values:
level:|dev, staging, prod| = |prod
status:|active, inactive, suspended| = |active
color:|red, green, blue| = |blue
priority:|low, medium, high, critical| = |high
Note: true, false, and nil are reserved keywords and cannot be used as atom values.
Structs
Structs are collections of named, typed fields. The type annotation declares the shape; values are positional:
# Block form — one value per line
server:{host:str, port:int, debug:bool} = {
'localhost'
8080
false
}
# Inline form — comma-separated on one line
origin:{x:int, y:int} = { 0, 0 }
Values are matched left-to-right against the fields in the type annotation. The names and types live in the annotation — the value block contains only data.
Tuples
Tuples are ordered sequences of typed values. Like structs, but without field names:
# Inline tuple
version:(int, int, int) = (3, 45, 5678)
# Block form
version:(int, int, int) = (
3
45
5678
)
# Decimal point tuple
point:(dec, dec) = (1.5, 2.5)
Lists
Lists are homogeneous sequences — every element has the same type:
# Inline list
tags:[str] = ['alpha', 'beta', 'release']
# Block list
ids:[int] = [
12
14
26
78
]
# Empty lists are valid
empty-list:[str] = []
All composite types may be empty except atom sets. Empty structs and tuples are valid:
unit:{} = {}
empty:() = ()
Maps
Maps are key-value collections. The ; in the type declares key and value types; the ; in entries separates individual keys from values:
# Block map
users:<int ; str> = <
1 ; 'Alice'
2 ; 'Bob'
3 ; 'Charlie'
>
# Inline map
codes:<str ; int> = <'us' ; 1, 'gb' ; 44, 'jp' ; 81>
# Empty maps are valid
cache:<str ; int> = <>
Maps with composite values
Map values can be structs, tuples, or any other composite:
roster:<int ; {gn:str, fn:str, admin:bool}> = <
01 ; { 'Johnson', 'Amy', true }
02 ; { 'Smith', 'Bob', false }
>
Note: Duplicate keys within a map are preserved in encounter order. Higher-level consumers decide what that means for their domain.
Nullable Types
Append ? to any type to make it nullable. A nullable field can hold nil:
# Nullable scalars
nickname:str? = nil
score:int? = 42
# Nullable atoms
role:|admin, user|? = nil
status:|active, inactive|? = |active
# Nullable composites
config:{host:str, port:int}? = nil
# Lists of nullable elements
sparse:[int?] = [1, nil, 3, nil, 5]
# Various nullable types
maybe-flag:bool? = nil
maybe-price:dec? = 9.99
maybe-stamp:ts? = nil
Using nil with a non-nullable type is a parse error — you must opt in with ?.
A Realistic Unit
This example shows a production deployment configuration using structs, lists, maps, tuples, nullable types, and atoms together:
# Deployment configuration
# Generated for environment: production
app-name:str = 'midwatch'
version:(int, int, int) = (2, 14, 0)
# Deployment target
deploy:{level:|dev, staging, prod|, release:int, date:date} = {
|prod
26
2026-06-01
}
# Feature flags
features:[str] = [
'dark-mode'
'notifications'
'audit-log'
]
# Primary database connection
db:{host:str, port:int, name:str, pool-size:int} = {
'db.prod.internal'
5432
'midwatch_prod'
20
}
# Replica endpoints — list of structs
replicas:[{host:str, port:int}] = [
{ 'replica-1.prod.internal', 5432 }
{ 'replica-2.prod.internal', 5432 }
]
# Nullable fields
tls-fingerprint:str? = 'sha256:a1b2c3d4e5f6'
rollback-version:(int, int, int)? = nil # not set
# Service metadata map
meta:<str ; str> = <
'owner' = 'platform-team'
'region' ; 'us-east-1'
'tier' = 'critical'
>
# Health check configuration
health:{endpoint:str, interval-sec:int, timeout-sec:int, healthy-threshold:int} = {
'/healthz'
30
5
3
}
active:bool = true
instance-count:int = 4
started:ts = 2026-06-01T14:30:00Z
This unit uses nearly every PAKT feature: scalars, strings, atoms, structs, tuples, lists, maps, nullable types, and comments. Every field is self-describing — the type annotation tells you exactly what to expect.