Standard library
gale_std provides typed interfaces to common Elixir and OTP functionality.
Add it to the dependency list in mix.exs, then alias the modules you use:
{:gale_std, git: "git@github.com:cloudloom-ai/gale.git", branch: "main", subdir: "libs/gale_std"}alias gale_std.listalias gale_std.optionalias gale_std.stringUse this page to find a module, understand its return values, and choose common operations. For every function’s signature and documentation, see the standard-library source.
Choose a module
Section titled “Choose a module”| I need to… | Module |
|---|---|
| Work with an optional value | gale_std.option |
| Transform or recover from a result | gale_std.result |
| Process a list | gale_std.list |
| Process values lazily | gale_std.stream |
| Work with maps, sets, or keyword lists | gale_std.map, gale_std.map_set, gale_std.keyword |
| Work with UTF-8 text or raw bytes | gale_std.string, gale_std.binary |
| Convert numbers and atoms | gale_std.integer, gale_std.float, gale_std.atom |
| Work with an Elixir integer range | gale_std.range |
| Validate dynamic data or JSON | gale_std.decode, gale_std.json |
| Read files and paths | gale_std.file, gale_std.path |
| Work with dates, URIs, and time | gale_std.date, gale_std.date_time, gale_std.uri, gale_std.time |
| Print, inspect, or log | gale_std.io, gale_std.inspect, gale_std.logger |
| Read environment values or use crypto | gale_std.system, gale_std.crypto |
| Start processes and exchange messages | gale_std.process |
| Build OTP services | gale_std.gen_server, gale_std.supervisor, gale_std.application |
| Run tasks or dynamic children | gale_std.task, gale_std.task_supervisor, gale_std.dynamic_supervisor |
| Use Registry, ETS, or persistent term | gale_std.registry, gale_std.ets, gale_std.persistent_term |
| Write Gale tests | gale_std.test |
Option and Result
Section titled “Option and Result”Option<A> represents presence or absence. Use case with Some(value)
and None, or use gale_std.option:
| Function | Result |
|---|---|
is_some?, is_none? |
Test which constructor is present |
unwrap_or(option, default) |
Return the value or a fallback |
map(option, transform) |
Transform Some; preserve None |
and_then(option, transform) |
Chain a function returning Option |
flatten(option) |
Remove one nested Option layer |
from_nil(value), to_nil(option) |
Convert at Elixir nil boundaries |
to_result(option, error) |
Convert to Result<A, E> with a caller-chosen error |
Result<A, E> represents expected success or failure. Use case with
Ok(value) and Error(reason), chain results with with, or use
gale_std.result:
| Function | Result |
|---|---|
is_ok?, is_error? |
Test which constructor is present |
unwrap_or(result, default) |
Return the success value or a fallback |
map(result, transform) |
Transform Ok; preserve Error |
map_error(result, transform) |
Transform the error |
and_then(result, transform) |
Chain a function returning Result |
to_option(result) |
Keep an Ok value and discard an error as None |
Prefer Option when absence is expected and needs no reason. Prefer Result
when the caller needs to know why an operation failed.
Collections
Section titled “Collections”Use gale_std.list to construct, inspect, transform, search, and aggregate
lists. Gale has no Enumerable protocol, so each collection module owns its
operations and lazy traversal stays in gale_std.stream.
| Task | Common operations |
|---|---|
| Construct or rearrange a list | list.range, list.duplicate, list.reverse, list.flatten |
| Read an element | list.first, list.last, list.at |
| Transform or filter | list.map, list.flat_map, list.filter, list.reject |
| Search or test | list.find, list.any?, list.all?, list.member? |
| Accumulate a value | list.reduce, list.reduce_while, list.sum |
| Sort or group | list.sort, list.sort_by, list.group_by, list.frequencies |
| Split or combine | list.take, list.drop, list.chunk_every, list.zip |
list.first, list.find, list.min, and list.max return Option when an
element may be absent.
names = users |> list.filter(fn(user) -> user.active) |> list.map(fn(user) -> user.name) |> list.sort()Streams
Section titled “Streams”gale_std.stream.Stream<A> is lazy and distinct from List<A>. Build a stream
with from_list, transform it with map, filter, take, or each, then
consume it with to_list, reduce, or into_file.
first_ten = values |> stream.from_list() |> stream.map(fn(value: Integer) -> value * 2) |> stream.take(10) |> stream.to_list()Maps, sets, and keyword lists
Section titled “Maps, sets, and keyword lists”Use gale_std.map for Map<K, V> values:
| Operation | Result |
|---|---|
get(map, key) |
Option<V>; distinguishes a missing key from a stored nil |
get(map, key, default) |
The stored value or the default |
put(map, key, value) |
A map with the key inserted or replaced |
delete(map, key) |
A map without the key |
pop(map, key) |
The optional value and the remaining map |
keys(map), values(map), to_list(map) |
Lists of keys, values, or key-value tuples |
The module also supports merging, filtering, and updating values with a function.
gale_std.map_set.MapSet<A> is the typed Elixir set. The module provides
construction, membership, insertion, deletion, union, intersection,
difference, size, and list conversion.
gale_std.keyword works with List<{Atom, V}> and provides typed keyword
lookup and updates.
Text, bytes, and conversion
Section titled “Text, bytes, and conversion”String is UTF-8 text and Binary is arbitrary bytes. A String can be used
where a Binary is expected. Converting bytes to text requires validation:
case string.from_binary(bytes) { Ok(text) -> string.upcase(text) Error(:invalid_utf8) -> "invalid text"}| Task | Common operations in gale_std.string |
|---|---|
| Validate bytes as text | valid?, from_binary |
| Inspect text | length, empty?, contains?, starts_with?, ends_with? |
| Transform text | trim, upcase, downcase, replace |
| Split or combine | split, graphemes, codepoints, join |
| Read part of a string | first, last, at, slice |
gale_std.binary provides byte-oriented byte_size, part, and append.
Use gale_std.integer and gale_std.float for numeric conversion, parsing,
predicates, and bounds. Float add, subtract, multiply, and divide return
Result<Float, gale_std.number.ArithmeticError> and handle arithmetic overflow;
divide also handles both signed zero divisors. Binary Float arithmetic
operators are rejected so these failures stay values.
gale_std.number owns this shared native error type for both integer and Float
operations.
gale_std.atom.to_existing converts text without
creating a new atom.
Dynamic data and JSON
Section titled “Dynamic data and JSON”A decode.Decoder<A> is a function from Term to
Result<A, decode.DecodeError>. Primitive decoders include string, binary,
integer, float, and boolean. Compose them with list, dictionary,
field, optional_field, nullable, map, and and_then.
pub fn user_decoder() -> decode.Decoder<%{name: String, age: Integer}> { fn(input) -> with { name <- decode.field(input, "name", decode.string()) age <- decode.field(input, "age", decode.integer()) %{name: name, age: age} }}decode.field requires the field. decode.optional_field permits it to be
absent. decode.nullable accepts JSON null and returns None; it does not
make an object field optional.
gale_std.json.parse(text, decoder) distinguishes malformed JSON from a valid
JSON value with the wrong shape. For output, build the closed Json type with
string, integer, float, boolean, null, array, and object, then use
encode or encode_with. See the Decoding tour for a complete
encoder and decoder.
Files, system values, and output
Section titled “Files, system values, and output”gale_std.file.read returns bytes. Use read_text when the file must be valid
UTF-8. write accepts bytes; a String is accepted because it is a subtype
of Binary. The module also provides existence checks, directory creation and
removal, file removal, and lazy stream_lines and stream_bytes.
gale_std.path joins and inspects path components. gale_std.system.get_env
returns Option<String>. Use gale_std.date and gale_std.date_time for dates,
gale_std.uri for URIs, gale_std.time for clocks, and gale_std.crypto for
cryptographic operations.
Use gale_std.io for terminal input and output, gale_std.inspect.inspect to
turn any Term into text, and gale_std.logger for Logger levels and metadata.
OTP and concurrency
Section titled “OTP and concurrency”Processes
Section titled “Processes”gale_std.process.Pid<M> carries the type of messages a process accepts.
spawn and spawn_link create typed processes; self returns a Pid matching
the current function’s receives declaration; send accepts only the Pid’s
message type.
The module also provides links, monitors, timers, exits, make_ref, and native
Down and ExitEvent message types. AnyPid can identify a process for these
operations but cannot be used to send an arbitrary message.
GenServer
Section titled “GenServer”gale_std.gen_server.Server<Args, State, Call, Cast, Info, Continue> describes
a native GenServer. Call is a reply-indexed request type, so each request
constructor determines the result of gen_server.call.
pub type Request<Reply> = | Count : Request<Integer> | Add(amount: Integer) : Request<Integer>
pub fn count(server: CounterTarget) -> Integer { gen_server.call(server, Count)}The module exposes typed start_link, child_spec, call, cast, send,
reply, stop, names, and lookup. CallServer, CastServer, and Worker
aliases fill unused protocols with Never. See the OTP tour for
a complete implementation.
Supervision, applications, and tasks
Section titled “Supervision, applications, and tasks”gale_std.supervisor and gale_std.application expose native OTP behaviours
through declares and implements. Child specifications and return values keep
their normal Elixir representations. gale_std.dynamic_supervisor manages
children at runtime.
gale_std.task.Task<A> tracks the result type of a task.
Use task.async for short caller-owned work and gale_std.task_supervisor for
supervised typed tasks. These are native Task and Task.Supervisor processes with
compile-time type parameters.
Registry, ETS, and persistent term
Section titled “Registry, ETS, and persistent term”These modules track resource identity and value types at compile time. The type parameters add no runtime wrapper:
| Type | Tracks |
|---|---|
Registry<Name, Key, Value> |
Registry identity, key type, and stored value |
Ets<Name, Key, Value> |
Table identity, key type, and stored value |
PersistentKey<Value> |
The value associated with a persistent key |
Operations that declare raises ArgumentError return a Result for that
exception. Check the function signature for its error type.
Testing
Section titled “Testing”Gale test modules live under test/, end in _test, and expose public
zero-argument functions as ExUnit tests. gale_std.test includes assert,
refute, assert_equal, assert_not_equal, assert_raises, assert_exit,
assert_log, and start_supervised.
mod shop.total_test
alias gale_std.testalias gale_std.list
pub fn adds_prices() -> :ok { test.assert_equal(list.sum([10, 20]), 30)}Assertions are ordinary library functions. Runtime type checks are enabled in
tests through gale: [runtime_typechecks: Mix.env() == :test] in mix.exs.
Interop rules
Section titled “Interop rules”The standard library preserves native BEAM values: lists remain lists, maps remain maps, Pids remain Pids, and OTP functions keep their conventional return shapes. Type parameters on processes and resources are compile-time contracts; they are erased at runtime. Foreign Elixir code must obey those contracts.
Expected native exceptions are converted only where an API declares
raises E. Exits and undeclared exceptions retain their native behaviour. For
the exact model, see trusted typed interfaces.