tricu

A lazy functional language based on Tree Calculus
Log | Files | Refs | README | LICENSE

getting-started.md (11877B)


Write and run tricu in the Arboricx playground

tricu is the source language. Arboricx bundles carry its compiled, named tree values between runtimes. The playground at arbori.cx lets you edit modules, inspect compiled definitions and explicitly run IO using Haskell WebAssembly.

Basic Examples starts with Names and values, then introduces arithmetic, functions, lists, transformations and choices. Each lesson includes definitions, expected results and small edit exercises. Write applications in Source as definitions you can inspect. For a compact syntax tour, select Language & Runtime Explorations → Language reference.

A complete first program

Choose Names and values in the Program selector. Replace its Source with:

!export answer

identity x = x
answer = identity 42

After a pause, the status becomes Compiled. Click the underlined answer name; Auto → Natural number displays 42. To explore a different application, write another named definition in Source and click its underlined name. Source edits compile automatically. During compilation or pure observation, Stop discards the active runtime; edit again or use Compile now in Settings to prepare the current draft. Running IO uses cooperative cancellation, described below. Restore published source restores the selected demo. Settings also offers scratch examples.

!export answer selects the public bundle interface. Locally compiled private definitions are inspectable too. Every native module needs at least one export; !export * exposes its local definitions.

Inspect a compiled definition

Click an underlined top-level definition name to open its tree inside the source editor. Auto tries readable text, a natural number, a list of text/naturals, a Boolean, bytes, then tree source, and labels its choice (for example Auto → Text). This is a display preference, not an inferred type. Empty trees default to natural zero. Control characters (except TAB/LF/CR), private-use and unassigned Unicode do not count as readable text, but remain available through manual Text. Choose another interpretation whenever the default meaning is not the one you intend. Lists decode up to 4,096 text/natural elements; numbers retain their exact decimal representation, including values beyond JS safe integers. Interpretations assign meaning to tree shapes; an incompatible decoder reports an error without changing the definition. No arguments are applied. Opening a card never executes IO. Auto first checks for the supported IO envelope, as described below.

Open inspections refresh after successful compilation, preserving a manual interpretation. Edit name closes the card and selects the identifier for renaming. Tab then Enter/Space also opens a highlighted name. Ordinary references and local variables remain text; uncompiled names have no clickable underline.

Use the × at the card's top-right, press Escape, or click the name again to close the card. The close button stays in the header while the card scrolls. Reopening starts with Auto. Editing, failed compilation, and a hard runtime Stop clear the old tree. Published packages expose only their public definitions; private bindings become inspectable after editing compiles the source locally. Reading/decoding trees can require reduction and can diverge; Stop terminates the owning runtime. Inline text previews show at most 16,384 characters; Copy and Download in the card include the complete output. After stopping pure observation, recompile/reload and click the definition name to retry; recompilation does not automatically restart a cancelled observation.

Find and import libraries

Use Explore libraries… in the toolbar. Search by library purpose or exported name; Libraries and Definitions have separate result groups. Select a definition to see its library, namespace and reference, or browse a library's clickable exports. Choose a namespace, then Insert import. Imports acquire the whole module, not one definition. No application or example binding is generated for you. Without editable source, Open library loads the published library; use its stored-definition search to inspect individual exports directly. Browsing and closing the explorer never change your draft. The Program selector focuses on examples, with a compact entry for the currently explored library. The picker checks the candidate with the native compiler and inserts one undoable edit. Existing imports have a jump action; ambiguous or unfinished source can use Copy import. Cancel closes the check. Installed local files appear alongside published libraries. Historical releases are available in the version selector.

For text-only assistance, use the library directory. Each release page includes its full manifest-hash import statement, complete exported names, available calling conventions, and source references. The machine-readable library index contains the same release identities and names. Choose a published version explicitly. Use its manifest as the import identity; its separate bundle SHA-256 identifies the downloadable file.

The playground resolves published and page-local manifests. The CLI additionally resolves workspace source names such as !import prelude *; translate those names to published manifest imports when adapting CLI examples for the playground. Qualified imports make calls explicit: N.add 20 22. Imports belong in the module header, before definitions. Imported names are available to your source definitions, while reexports select the public interface. See modules.

Write source with the available syntax

Read the language feature guide for practical conventions and the language contract for exact syntax. In particular, B.lazyBool thenThunk elseThunk condition takes branches before its condition; B.matchResult onError onSuccess result passes both value/diagnostic and remainder to a handler. Library protocols matter as much as function names.

Run IO inside a definition card

Select the conversation demo and click the underlined main name. A tree with the "tricuIO" sentinel and supported version 2 envelope opens an IO program card. Recognition examines the envelope only, not its action or continuations. It can still require reduction or diverge; Stop stays available.

Click Run IO to execute. The card contains streamed terminal output, a line input when requested, and Stop. IO details holds stepping/Next, an interaction trace and the returned-value interpretation for the next run. Changing interpretation never reruns IO automatically. The definition's normal format selector remains available for inspecting its tree representation. An unapplied function that returns IO has no envelope yet: write its application as a source definition first. Closing a running IO card requests cancellation and waits for cleanup. Completed IO cancellation retains the compiled definitions. Editing or replacing source invalidates previous recognition/results.

Browser IO supports core sequencing, scopes, child tasks and cancellation, plus standard byte streams and UTF-8 codecs. The terminal displays output and offers line-oriented input with Send and EOF controls. Use the published io and io-text 0.11.0 releases in the worked examples for current IO construction and text helpers. Historical version-1 IO trees remain inspectable as data. File, network, process and clock facilities need an appropriately configured native host; IO.capabilities reports the available facilities. An envelope is recognition of the protocol, not proof that every action is valid or that the program terminates.

Choose an output interpretation

Value Definition-card interpretation
Natural number Natural number
Character list Text
Boolean Boolean
List of text/naturals List · text / numbers
General list, pair, function or other tree tricu, △ source, DAG or Ternary
Wrapped IO action Auto offers explicit Run IO; tree formats inspect its representation

Text expects a character list, not a list of strings. Unsupported decoded list items fail rather than returning a partial list. The tested examples include complete source, the definition name to click, card instructions and independent expected results. Inspect a pure definition's result directly in its card; use Run IO for an IO definition. Settings → Published package → Stored definition export downloads original package records without reducing the tree or running IO.

Share programs and handle diagnostics

Copy published selection link in Settings shares the selected published package. To share an edited draft, copy its Source or export its compiled public interface.

Export compiled module in Settings downloads the current public interface as an .arboricx file. Settings → Local modules validates an imported file and makes its manifest available to source imports. Local files stay in page memory through Stop and are cleared on reload. Exported bundles include the executable trees reachable from the public interface.

A compilation diagnostic belongs to the current source. Fix it before inspecting or running the draft. Check spelling, exported names, manifest identities, argument order, required fallback patterns and indentation. A successful compilation still allows a computation to diverge; Stop remains available. The editor currently accepts 16,384 source scalars, 4,096 local definitions and up to 4,096 imported/public names. Large computations may exceed browser memory.

Guidance for text-only assistants

Start with this guide and the library directory. Fetch the release pages needed for the task, and consult source/protocol references for unfamiliar exports. Provide complete source with a named result/entry point, its interpretation, and whether to inspect it or explicitly run IO. Derive expected results explicitly and distinguish a proposed program from one you have actually run. Published interfaces and these static references are readable through ordinary HTTP; playground execution is optional for looking up names, imports and conventions.

Recover a stuck runtime

Use Reload Playground in the toolbar if the runtime stops responding or repeatedly errors after an idle period. This reloads the whole page, including all WebAssembly sessions. It stays available while other work is running. If you have a local draft or opened modules, confirm before discarding them; cancel to copy your work first. Reload also clears inspection results, IO state and the local-module collection, and loads the normal URL/default selection without automatically evaluating it.