Skip to content

What is AIVI?

AIVI is a purely functional, reactive, statically typed language designed for one purpose: building native Linux desktop applications that are correct by construction.

If you have used React, Elm, or SwiftUI, some ideas will feel familiar — reactive state, declarative UI, immutable data. But AIVI is not a framework inside another language. It is the language itself.

What you need to know up front

AIVI does not have if/else, for loops, mutable variables, or null. Instead:

Familiar conceptAIVI equivalent
if/elsePattern matching with ||>, T|>, F|>
for loopsCollection combinators: map, filter, reduce
Mutable variablesSignals — reactive values in a dependency graph
NullOption — explicit presence or absence
Callbacks / event handlersSources and when clauses

If this sounds unusual, Thinking in AIVI explains the mental model shift in detail.

A tiny first example

This is a complete, valid AIVI module:

aivi
type Text -> Text
func formatGreeting = name =>
    "Hello, {name}!"

value greeting = formatGreeting "Ada"

It already shows the two most common top-level forms:

  • func for a named pure function
  • value for a named constant

A first signal

Signals represent values that participate in the reactive graph:

aivi
type Int -> Int
func double = n =>
    n * 2

signal count = 21

signal doubledCount = count
  |> double

The important idea is that doubledCount is defined from count, not assigned later. When count changes, doubledCount recomputes automatically. You declare the relationship once; the runtime handles the rest.

A first UI

AIVI markup is an ordinary expression that describes GTK widgets:

aivi
signal count = 42

signal label = count
  |> "Count: {.}"

value main =
    <Window title="My App">
        <Label text={label} />
    </Window>

export main

The <Label> attribute text={label} binds to the label signal. When count changes, the label updates. No manual subscriptions, no setState, no render loop.

Key concepts

ConceptWhat it isLearn more
valueA named constant expressionValues & Functions
funcA named pure functionValues & Functions
signalA reactive value in the dependency graphSignals
@sourceAn external data feed (timer, keyboard, HTTP, etc.)Sources
typeAn alias, record, or tagged unionTypes
domainA branded type with its own operatorsDomains
|>Pipe — sends a value into a functionPipes & Operators
||>Pattern match — branches on a valuePattern Matching

Why it feels different

Most reactive systems add dataflow on top of an imperative host language. AIVI makes dataflow the default shape of the program, so dependencies stay visible in the source.

That is why the language leans so heavily on named declarations and pipes: the reactive graph is meant to be readable. You should be able to look at any signal and trace where its value comes from, without searching for mutation sites or callback registrations.

Where to go next

Choose your path:

AIVI Language Manual