Modules
Each .aivi file is a module. Modules import names with use and expose names with export.
Importing with use
use aivi.http (
HttpError
HttpResponse
)
use aivi.result (isOk)Imported names become available to the rest of the file.
When you want the whole exported surface of a module, omit the import list:
use aivi.httpThat form brings every exported name from aivi.http into the local file scope.
Import aliases
Use as when you want a local name that differs from the exported one:
use aivi.http (
HttpError as FetchError
HttpResponse as Response
)
type Response Text -> Bool
func isSuccess =
||> Ok _ -> True
||> Err _ -> FalseExporting names
A data type and its same-named constructor occupy separate type and value namespaces. One export exposes both:
type Box A = Box A
export BoxIf another module imports this as use models (Box as Container), then export Container forwards both the type and the genuine constructor. Further aliases preserve the original type identity and variant name, so Container works in type annotations, constructor applications, and case patterns. Re-exporting the carrier also forwards its public class instances from their original implementation module.
The two imported namespaces must belong to the same canonical data declaration. A function that happens to return that type does not qualify as its constructor; unrelated declarations and multiple bindings in one namespace remain ambiguous.
You can export one name:
value greeting = "hello"
export greetingOr several names together:
type Direction =
| Up
| Down
| Left
| Right
type Direction -> Direction
func opposite =
||> Up -> Down
||> Down -> Up
||> Left -> Right
||> Right -> Left
value startDirection : Direction = Right
export (Direction, opposite, startDirection)A small complete module
use aivi.text (
trim
toUpper
)
type Text -> Text -> Text
func joinLabels = left right =>
"{left}/{right}"
value primaryLabel = "primary"
value fallbackLabel = "fallback"
value labelPair = joinLabels primaryLabel fallbackLabel
export labelPairTypical module layout
A practical order is:
usetype/domain/classfuncandvaluesignalexport
That ordering is not required by the language, but it keeps modules easy to scan.
Publishing names project-wide with hoist
hoist is a self-declaration: a module declares that its own exports should be lifted into the project-wide namespace. Every other .aivi file in the project can then use those names directly, without any use statement.
// libs/types/ids.aivi
hoist
domain AccountId over Text// libs/types/mail.aivi
hoist
type Message = {}Any file in the project can then use AccountId, Message, etc. without any use statement. To show the contrast — a consuming file needs no imports at all:
// apps/ui/view.aivi — no use or hoist needed here
type AccountId -> Text -> Widget
func accountLabel = id label => ...The stdlib prelude
Several commonly used standard library modules declare hoist:
// stdlib/aivi/list.aivi
hoistTogether with the compiler's ambient prelude, this makes names such as map, filter, length, getOrElse, and isOk available without an explicit import. Not every stdlib module hoists its exports: use the import shown on each module's reference page.
Kind filters
When you only want to publish specific kinds of exports:
hoist (func, value)Valid kind filters: func, value, signal, type, domain, class.
Hiding specific names
Suppress individual names from the hoist:
hoist hiding (head, tail)Combine kind filters and hiding:
hoist (func) hiding (foldr, foldl)Name disambiguation
Ambient class methods such as map are resolved through class evidence before hoisted helpers. For other names shared by hoisted modules, the compiler uses type context to disambiguate:
type Int -> Int
func double = . * 2
type Text -> Text
func greet = "Hello, {.}"
value numbers = [1, 2, 3]
value doubled : List Int = map double numbers
value maybeName = Some "Alice"
value greeting : Option Text = map greet maybeNameIf the type context is insufficient, the compiler reports an error and suggests using hiding to exclude the conflicting name from one of the hoisted modules.
Priority order
local definitions > use imports > class methods > hoisted globals > other ambient namesAn explicit use aivi.list (map) selects the list helper in that file. Without that import, map remains class-polymorphic even when list helpers are hoisted.
Type names follow the same local/import/hoist priority before ambient fallback. An imported domain therefore retains its own declaration identity and carrier even when the ambient prelude supplies a domain with the same name.
use always wins over hoist for the same name, so you can override a hoisted name locally for a specific file.
Summary
| Form | Meaning |
|---|---|
use module | Import every exported name from this module into this file |
use module (names) | Import selected names into this file |
use module (name as localName) | Import one name under a local alias |
export name | Export one name to importers |
export (a, b, c) | Export several names to importers |
hoist | Publish this module's exports to the whole project |
hoist (func, value) | Publish only selected kinds project-wide |
hoist hiding (a, b) | Publish all except named items project-wide |