Skip to main content
Version: 1.0.0

Classify typed tickets

Build a deterministic business decision: classify a ticket by its overdue duration and select the first usable contact address. This walkthrough combines an enum, an optional, branches and a loop without a model or external service.

1. Write the program​

Create triage.tb:

triage.tb
module examples.typed_triage

enum Priority
normal
watch
urgent

type Triage
priority is Priority
contact is Optional of Text

function Classify
takes days as Int
gives Priority
do
if days >= 7
give Priority.urgent
else if days >= 3
give Priority.watch
else
give Priority.normal

function FirstContact
takes contacts as List of Optional of Text
gives Optional of Text
do
for contact in contacts
if present contact as address
if address != ""
give some(address)
give none(Text)

strategy Run
takes days as Int
takes contacts as List of Optional of Text
gives Triage
uses Classify
uses FirstContact
do
Classify
with days as days
into priority
FirstContact
with contacts as contacts
into contact
give record Triage { priority as priority, contact as contact }

Functions calculate values; the strategy composes their results. No manifest or handler is needed.

2. Compile and run​

touba compile triage.tb --out triage.air.json
touba run triage.air.json \
--entry strategy:examples.typed_triage/Run \
--inputs-json '{"days":8,"contacts":[{"present":false},{"present":true,"value":"a@example.test"}]}' \
--output result

Expected result:

{"priority":"urgent","contact":{"present":true,"value":"a@example.test"}}

3. Check boundaries​

Run the same command with these inputs:

InputsExpected result
{"days":3,"contacts":[]}watch and {"present":false}
{"days":0,"contacts":[{"present":true,"value":""}]}normal and {"present":false}
{"days":8,"contacts":[null]}EntryInputSchemaInvalid refusal

Absence is not null. Empty text is present, but the business rule chooses to ignore it. These checks belong to different layers: the runtime validates the typed shape; the function expresses the project's rule.

Continue​

See Enumerations, Optional values and Conditions and iteration, then automate these checks.

Build a readable notification​

This standalone module adds an exhaustive label and a typed template. Here the application supplies a positive duration in minutes.

notification.tb
module examples.notification

enum Priority
normal
watch
urgent

function Label
takes priority as Priority
gives Text
do
match priority
case Priority.normal
give "Normal"
case Priority.watch
give "Follow up"
case Priority.urgent
give "Urgent"

function Notify
takes priority as Priority
takes elapsed_minutes as Int
gives Text
do
Label
with priority as priority
into label
give f"{label}: {text(elapsed_minutes // 60)} h {text(elapsed_minutes % 60)} min"
touba compile notification.tb --out notification.air.json
touba run notification.air.json \
--entry function:examples.notification/Notify \
--inputs-json '{"priority":"urgent","elapsed_minutes":125}' \
--output result

Result: "Urgent: 2 h 5 min". // computes the integer quotient and % the remainder. text(...) explicitly renders numbers inside the template. Removing a case reports NonExhaustiveMatch; inserting a number without text(...) is rejected. A template cannot resolve a secret by its name.