README

ihb2032/MoonFrame/types does not have a README file

#
DataError

pub(all) suberror DataError {
ColumnNotFound(String)
DuplicateColumn(String)
TypeMismatch(TypeMismatchDetail)
LengthMismatch
IndexOutOfBounds(Int)
ParseError(ParseErrorDetail)
InvalidOperation(String)
IoError(String)
Unsupported(String)
NullInNonNullable(String)
} derive(Eq,
Debug
)

Unified error type for all MoonFrame operations.
impl Show for DataError

#
DataError::equal

fn DataError::equal(DataError, DataError) -> Bool

#
DataError::message

fn DataError::message(self : DataError) -> String

Human-readable message describing the error.

#
DataError::not_equal

fn DataError::not_equal(x : DataError, y : DataError) -> Bool

#
DataError::output

fn DataError::output(self : DataError, logger : &Logger) -> Unit

#
DataError::to_string

fn DataError::to_string(self : DataError) -> String

#
CellParseLocation

pub(all) enum CellParseLocation {
Row
Record
Line
} derive(Eq,
Debug
)

Identifies how a typed cell's 1-based source position is reported. Row is used by CSV, Record by JSON arrays, and Line by NDJSON.

#
CellParseLocation::equal

#
CellParseLocation::not_equal

fn CellParseLocation::not_equal(x : CellParseLocation, y : CellParseLocation) -> Bool

#
ClosedInterval

pub(all) enum ClosedInterval {
Both
Left
Right
None
} derive(Eq,
Debug
)

Which endpoints an is_between range includes — Polars' closed. Both (the default) is lo <= x <= hi; Left / Right open the other end; None excludes both (lo < x < hi).

#
ClosedInterval::equal

#
ClosedInterval::not_equal

fn ClosedInterval::not_equal(x : ClosedInterval, y : ClosedInterval) -> Bool

#
DataType

pub(all) enum DataType {
Int
Float
Bool
String
Null
} derive(Eq,
Debug
)

Logical data type for a column.

Null is the dtype of a missing value, not of a column: it is what Scalar::Null.dtype() reports, and so what a TypeMismatch's "expected T, got Null" names when a null cell reaches a typed read. A hand-built Schema may also carry it, but nothing materialises a column on it — DataFrame::empty raises Unsupported for such a field, cast refuses it as a target, and no reader infers it: an all-null probe window falls back to String (see docs/type-inference.md). Concrete columns always carry one of the other variants.
impl Show for DataType

#
DataType::equal

fn DataType::equal(DataType, DataType) -> Bool

#
DataType::is_bool

fn DataType::is_bool(self : DataType) -> Bool

true only for the Bool variant.

#
DataType::is_float

fn DataType::is_float(self : DataType) -> Bool

true only for the Float variant.

#
DataType::is_integer

fn DataType::is_integer(self : DataType) -> Bool

true only for the Int variant.

#
DataType::is_numeric

fn DataType::is_numeric(self : DataType) -> Bool

true for Int and Float — both are usable in numeric reductions.

#
DataType::is_string

fn DataType::is_string(self : DataType) -> Bool

true only for the String variant.

#
DataType::not_equal

fn DataType::not_equal(x : DataType, y : DataType) -> Bool

#
DataType::output

fn DataType::output(self : DataType, logger : &Logger) -> Unit

#
DataType::to_repr

#
DataType::to_string

fn DataType::to_string(self : DataType) -> String

#
Field

pub struct Field {
// private fields
} derive(Eq,
Debug
)

Column metadata: a name, the column's logical DataType, and a declared nullable flag.

nullable = false is a declared constraint that DataFrame::from_rows enforces: row data placing a Scalar::Null in such a column raises NullInNonNullable(name). (DataFrame::empty builds 0-row columns, so it can never violate the constraint.) The flag is never inferred from a column's contents: the constructor's nullable default — and so DataFrame::DataFrame and the IO readers — always sets nullable = true, so a nullable = false field only ever originates from an explicit Field::Field(..., nullable=false) in a caller-supplied schema.

Once declared, it travels with the cells it describes. Every operation that moves a column carries its field rather than re-deriving one: Field::rename (and so DataFrame::rename / rename_with, which change nothing but the name), Schema::select / Schema::rename, the row-only frame transforms that reuse their input's schema verbatim (head / tail / slice / filter / sort / unique / fill_null / …), and the projections: a select or with_columns entry that is a bare col("x") (or an aliased one, which carries the field renamed), every column drop or select leaves in place, and the counter-prepending with_row_index. A column replaced through with_columns takes the field of whichever column now supplies its cells.

An operation that computes cells derives a fresh field instead, with the constructor default: arithmetic, aggregations, cast, fill_null as an expression, group_by(...).agg(...), join (an outer one introduces nulls), and the summary frames (describe / null_count / sum / …). The declaration was made about the input's cells, not about these.

That split is what keeps the flag honest without ever inspecting a column: it is validated once, by from_rows, and thereafter only accompanies cells it was validated against — the operations that carry it drop, reorder or rename, and never introduce a value.

The fields are priv, so the struct is opaque outside this package: build one through Field::Field(...) and read it through name() / dtype() / nullable(). That is what actually keeps a future field additive — a readable field is also matchable, and MoonBit requires a struct pattern to name every field or carry .., so a public field's arrival would break a caller's pattern exactly as a new pub(all) enum variant breaks a match.
impl Show for Field

#
Field::Field

fn Field::Field(name : String, dtype : DataType, nullable? : Bool) -> Field

Build a field. nullable defaults to true, the common setting for inferred CSV / JSON columns; pass nullable=false to declare the constraint DataFrame::from_rows enforces.

#
Field::dtype

fn Field::dtype(self : Field) -> DataType

The column's logical DataType.

#
Field::equal

fn Field::equal(Field, Field) -> Bool

#
Field::name

fn Field::name(self : Field) -> String

The column's name.

#
Field::not_equal

fn Field::not_equal(x : Field, y : Field) -> Bool

#
Field::nullable

fn Field::nullable(self : Field) -> Bool

The declared nullable flag (see the type doc for how DataFrame::from_rows enforces it).

#
Field::output

fn Field::output(self : Field, logger : &Logger) -> Unit

#
Field::rename

fn Field::rename(self : Field, new_name : String) -> Field

Return a copy of this field with a new name.

#
Field::to_repr

#
Field::to_string

fn Field::to_string(self : Field) -> String

#
NullOrder

pub(all) enum NullOrder {
NullsFirst
NullsLast
} derive(Eq,
Debug
)

Where missing cells go relative to non-missing ones. Missing means either a Null slot (validity bit 0) or — for Float columns — NaN. The plan specifies that NaN is treated identically to Null for ordering, so callers don't need a separate knob.

#
NullOrder::equal

fn NullOrder::equal(NullOrder, NullOrder) -> Bool

#
NullOrder::not_equal

fn NullOrder::not_equal(x : NullOrder, y : NullOrder) -> Bool

#
ParseErrorDetail

pub(all) enum ParseErrorDetail {
Message(String)
Cell(CellParseLocation, String, Int, DataType, String)
} derive(Eq,
Debug
)

Structured details carried by DataError::ParseError.

#
ParseErrorDetail::equal

#
ParseErrorDetail::not_equal

fn ParseErrorDetail::not_equal(x : ParseErrorDetail, y : ParseErrorDetail) -> Bool

#
Scalar

pub(all) enum Scalar {
Int(Int64)
Float(Double)
Bool(Bool)
String(String)
Null
} derive(Eq,
Debug
)

A single cell value in a DataFrame.

Null represents a missing value. The as_* conversions raiseTypeMismatch(Expected(expected, got, "")) on a wrong dtype (got = Null for a null cell). Comparisons raise TypeMismatch(...) on Null, or TypeMismatch(Operation("compare", left, right)) on an incomparable non-null pair — callers must check is_null() first or handle the error.

The Float variant carries a 64-bit Double; the Int variant carries a 64-bit Int64. Use as_float for explicit access; Int is also accepted via numeric promotion to Double.
impl Show for Scalar

#
Scalar::as_bool

fn Scalar::as_bool(self : Scalar) -> Bool raise DataError

Bool cells return their value; other concrete variants and Null raise TypeMismatch(Expected(...)).

#
Scalar::as_float

fn Scalar::as_float(self : Scalar) -> Double raise DataError

Float cells return their Double; Int cells are promoted to Double; other concrete variants and Null raise TypeMismatch(Expected(...)).

#
Scalar::as_int

fn Scalar::as_int(self : Scalar) -> Int64 raise DataError

Int cells return their Int64; other concrete variants and Null raise TypeMismatch(Expected(...)).

#
Scalar::as_string

fn Scalar::as_string(self : Scalar) -> String raise DataError

String cells return their value; other concrete variants and Null raise TypeMismatch(Expected(...)).

#
Scalar::dtype

fn Scalar::dtype(self : Scalar) -> DataType

The DataType corresponding to this value's variant.

#
Scalar::eq

fn Scalar::eq(self : Scalar, other : Scalar) -> Bool raise DataError

Equality between two Scalars. Two Nulls, or Null and a value, raise TypeMismatch — callers must guard nullability explicitly. Mixed numeric types (Int vs Float) compare exactly — the Int64 is not promoted to Double, so two distinct values never collide above 2^53 (e.g. Int(9007199254740993) is not equal to Float(9007199254740992.0), and Int64::MAX is not equal to the 2^63 Double a promotion would round it to). This is a deliberate departure from Polars' Float64-supertype promotion, chosen for correctness. NaN follows IEEE 754 (NaN == NaN is false).

#
Scalar::equal

fn Scalar::equal(Scalar, Scalar) -> Bool

#
Scalar::gt

fn Scalar::gt(self : Scalar, other : Scalar) -> Bool raise DataError

Strict greater-than, defined as other.lt(self) — same Null-raise and ordering rules as lt. The delegation transposes the operands, so the incomparable-dtypes diagnostic is issued here first, in the caller's operand order — Int(1).gt(String("x")) reports "Int and String", not the transposed pair eq / lt / lte would never produce.

#
Scalar::gte

fn Scalar::gte(self : Scalar, other : Scalar) -> Bool raise DataError

Greater-than-or-equal, defined as other.lte(self) — same rules as lte, with gt's call-order diagnostic for an incomparable pair.

#
Scalar::is_null

fn Scalar::is_null(self : Scalar) -> Bool

true only for the Null (missing-value) variant.

#
Scalar::lt

fn Scalar::lt(self : Scalar, other : Scalar) -> Bool raise DataError

Strict less-than. NaN follows IEEE 754: any comparison involving NaN returns false. Null short-circuits to raise. Mixed Int-vs-Float ordering is exact (no IntDouble promotion), so it never mis-orders two distinct values across the 2^53 boundary — the same deliberate departure from Polars as eq.

#
Scalar::lte

fn Scalar::lte(self : Scalar, other : Scalar) -> Bool raise DataError

Less-than-or-equal — eq or lt. Shares their Null-raise and exact Int/Float comparison semantics.

#
Scalar::not_equal

fn Scalar::not_equal(x : Scalar, y : Scalar) -> Bool

#
Scalar::output

fn Scalar::output(self : Scalar, logger : &Logger) -> Unit

#
Scalar::to_repr

#
Scalar::to_string

fn Scalar::to_string(self : Scalar) -> String

Value-style rendering: Int(42)"42", String("ab")"ab", Null"". Use the Show impl for the variant-form rendering.

#
Schema

pub struct Schema {
// private fields
} derive(Eq,
Debug
)

Ordered list of Fields describing a DataFrame's columns.

Construction always validates uniqueness of names; once built, a Schema is guaranteed to have no duplicate column names.

The fields array is priv: build a schema with Schema::Schema and read a copy via fields() / field_names(). External code cannot reach or mutate the backing array, so a validated schema stays valid.

index is the name→position map behind index_of, and through it field / select / rename. It is derived from fields and built in lock-step with it, never separately: the constructors are the only writers, and each one builds both. Uniqueness is what makes it total — every name maps to exactly the position that carries it — so it is the same validation pass that establishes both. A schema is immutable, so one scan at construction replaces a scan per lookup: resolving c names against a c-column schema was O(c²) while every resolution walked the array, which is the shape a wide select or rename hits.
impl Show for Schema

#
Schema::Schema

fn Schema::Schema(fields : Array[Field]) -> Schema raise DataError

Build a schema from a list of fields. raise DuplicateColumn(name) on the first repeated name.

The input array is copied, so mutating fields after construction cannot alter the schema or break the validated no-duplicates invariant.

The type's own constructor, like Field::Field — the spelling every canonically-constructed type in MoonFrame uses.

#
Schema::equal

fn Schema::equal(Schema, Schema) -> Bool

#
Schema::field

fn Schema::field(self : Schema, name : String) -> Field raise DataError

Return the Field for name, or raise ColumnNotFound(name).

#
Schema::field_at

fn Schema::field_at(self : Schema, i : Int) -> Field raise DataError

Return the Field at position i, or raise IndexOutOfBounds(i).

#
Schema::field_names

fn Schema::field_names(self : Schema) -> Array[String]

Column names in declaration order.

#
Schema::fields

fn Schema::fields(self : Schema) -> Array[Field]

Return a snapshot of the schema's fields.

A fresh array is returned so callers cannot mutate the schema in place and break the "no duplicate names" invariant enforced by Schema::Schema.

#
Schema::index_of

fn Schema::index_of(self : Schema, name : String) -> Int raise DataError

The index of the column named name, or raise ColumnNotFound(name). O(1) — the name index is built once, when the schema is.

#
Schema::is_empty

fn Schema::is_empty(self : Schema) -> Bool

true when the schema has no columns.

#
Schema::len

fn Schema::len(self : Schema) -> Int

Number of columns in the schema.

#
Schema::not_equal

fn Schema::not_equal(x : Schema, y : Schema) -> Bool

#
Schema::output

fn Schema::output(self : Schema, logger : &Logger) -> Unit

#
Schema::rename

fn Schema::rename(self : Schema, old_name : String, new_name : String) -> Schema raise DataError

Rename old_name to new_name. Raises if old_name is missing or new_name collides with another existing column.

#
Schema::select

fn Schema::select(self : Schema, names : Array[String]) -> Schema raise DataError

Project a sub-schema by name, preserving the order of names. Missing names raise ColumnNotFound(name); duplicates inside names raise DuplicateColumn(name).

#
Schema::to_repr

#
Schema::to_string

fn Schema::to_string(self : Schema) -> String

#
SortOrder

pub(all) enum SortOrder {
Asc
Desc
} derive(Eq,
Debug
)

Direction of a sort key. Asc sorts smaller values first, Desc sorts larger values first. The convention applies to every dtype: Int / Float use numeric ordering, Bool uses false < true, String uses lexicographic comparison.

#
SortOrder::equal

fn SortOrder::equal(SortOrder, SortOrder) -> Bool

#
SortOrder::not_equal

fn SortOrder::not_equal(x : SortOrder, y : SortOrder) -> Bool

#
TypeMismatchDetail

pub(all) enum TypeMismatchDetail {
Message(String)
Expected(DataType, DataType, String)
Operation(String, DataType, DataType)
} derive(Eq,
Debug
)

Structured details carried by DataError::TypeMismatch.

#
TypeMismatchDetail::equal

#
TypeMismatchDetail::not_equal