Skip to content

If you are new to functional programming ​

You do not need a functional-programming background to learn AIVI. You do need to accept that some familiar tools are replaced by different ones:

Familiar habitIn AIVI
Change a variable over timeDerive a new value, or move changing state into a signal
Write if / else chainsPattern-match with ||> or use T|> / F|>
Use loops for collectionsUse map, filter, reduce, and friends
Hide effects in library callsDeclare sources and let the runtime bridge them into the graph

Values are simpler than variables ​

A variable makes you ask, "what does this name mean right now?" A value removes that question.

aivi
value score = 10
value boostedScore = score + 5

score never becomes 15. boostedScore is a different value. That sounds small, but it removes an entire category of mental bookkeeping.

State still exists; it just moves ​

Functional programming does not ban change. It gives change a clearer home.

aivi
signal count = 21

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

The value of label changes over time, but the relationship stays fixed and visible in the source.

Branching becomes data-oriented ​

Instead of writing control flow around values, you branch on the value itself.

aivi
type LoadState =
  | Loading
  | Ready Text
  | Failed Text

type LoadState -> Text
func describe =
 ||> Loading      -> "Loading..."
 ||> Ready data   -> "Ready: {data}"
 ||> Failed error -> "Error: {error}"

The compiler checks that every case is handled. That is one of the main ergonomic wins of closed types.

Names should earn their keep ​

Beginners are often shown functional code full of clever temporary names. That is not the goal here. In AIVI, use the simplest readable form first:

aivi
type Text -> Text
func greeting =
  |> trim
  |> "Hello, {.}!"

Here . carries the trimmed text into the greeting; no temporary name is needed. For a case that needs both the original and transformed values, see remembering stage values.

(c) 2026 by Andreas Herd