118 Standard Library

Component layout

The Predica standard library is provided as an ordinary component named std. It is resolved from an include root in the same way as any other component.


-I root/
    std/
        _component_.predica
        folds.predica

With root/ supplied as an include root, this tree defines the component std. The file _component_.predica marks the component root, and folds.predica contains the standard fold declarations.

Every Predica source file can use selected standard library declarations without writing a using std; declaration. For example, standard folds such as count, exists, and empty are available as Σcount, Σexists, and Σempty. The standard library component can also be named explicitly as std.

Standard fold declarations

The standard fold declarations are:


component std;

// Plain E.Σ is primitive syntax and is not declared as a named fold.

// Cardinality folds
fold Integer count<Type T> = Σ{ 0 ; n value ↦ n + 1 };

fold Boolean exists<Type T> = Σ{ false ; found value ↦ true };

fold Boolean empty<Type T> = Σ{ true ; empty value ↦ false };

// Boolean folds
fold Boolean all =
    Σ{ true ; result value ↦ result ∧ value };

fold Boolean any =
    Σ{ false ; result value ↦ result ∨ value };

// Numeric folds
fold T sum<Type T> where T isa Real =
    Σ{ 0 ; total value ↦ total + value };

fold T product<Type T> where T isa Real =
    Σ{ 1 ; total value ↦ total * value };

fold Real mean<Type T> over input where T isa Real =
    input.Σsum / input.Σcount
    defined where input.Σcount > 0;

fold Real variance<Type T> over input where T isa Real =
    ((input - input.Σmean)^2).Σmean
    defined where input.Σcount > 0;

fold Real stddev<Type T> over input where T isa Real =
    sqrt(input.Σvariance)
    defined where input.Σcount > 0;

// Ordered folds
fold T min<Type T> where ordered(T) =
    Σ{ first value ↦ value ; best value ↦ if value < best then value else best };

fold T max<Type T> where ordered(T) =
    Σ{ first value ↦ value ; best value ↦ if best < value then value else best };

// Ordered-input folds
fold String concat =
    Σ{ "" ; text value ↦ text + value };

The standard cardinality folds satisfy the following laws for finite inputs:


items.Σexists = (items.Σcount > 0)
items.Σempty  = (items.Σcount = 0)
items.Σexists = not items.Σempty

These equations are laws, not definitions. Σexists and Σempty are defined directly so an implementation can recognise their logical meaning and avoid counting every value when that is not needed.

Some standard folds are intentionally listed before all of their supporting type constructors or declaration forms have been specified. For example, Σgroup remains part of the standard fold vocabulary as a planned map-producing fold even though its full declaration depends on the map and grouping model. Such entries are specification todos and should remain visible in the standard library chapter. A planned entry does not by itself introduce a usable std declaration; the fold becomes a standard fold when this chapter specifies its declaration, typing, and definedness rules.

Standard exception type

The standard library defines the common exception supertype used by catch clauses:


abstract value Exception
{
    String message?;
}

Concrete runtime exception values are instances of implementation-provided or library-provided subtypes of Exception. The standard prelude makes Exception available unqualified.

Prelude lookup

The declarations in std are ordinary component declarations, but every source file has a standard prelude scope. The prelude makes selected standard names available unqualified and makes std available as an explicit component qualifier. For folds this means the common standard folds are used without qualifying the component name:


items.Σcount
items.Σexists
items.Σempty

These expressions refer to std.count, std.exists, and std.empty. The standard spelling is deliberately items.Σcount, not items.Σstd.count. However, explicit qualification with std is legal and denotes the same fold:


items.Σcount      // canonical spelling for std.count
items.Σstd.count  // explicit qualified spelling for the same fold

Renderers and examples should prefer the unqualified standard spelling. The component name is still part of declaration identity and may be written when explicit disambiguation is useful.

The std qualifier is not a way to opt in to every aggregate name. A fold such as items.Σstd.median or items.Σstd.collapse is legal only if the standard library component actually declares median or collapse. In this specification those names are ordinary fold names, not predefined standard folds.

The prelude is not equivalent to writing using std;. Under the ordinary using rules, using std; would introduce a component alias only. The prelude also provides selected unqualified standard names.

Third-party folds and name clashes

Other components may define folds with the same local names as standard folds. For example, a statistics package may define its own count fold with different empty-input or weighting semantics. Such a declaration is legal, but an unqualified Σcount continues to mean the standard library fold. To use the third-party fold, qualify it with a component name or component alias:


using vendor.Stats as stats;

items.Σstats.count

Alternatively, a selected import may give the third-party fold a distinct local name:


using vendor.Stats { count as weightedCount };

items.ΣweightedCount

A selected import must not bind a non-standard fold to a local name that is a standard prelude fold name. For example, if count and mean are standard fold names, then this import is invalid:


using vendor.Stats { count, avg as mean };

The invalid import would try to bind vendor.Stats.count as the local fold name count, and vendor.Stats.avg as the local fold name mean. Those local names already belong to the standard prelude folds std.count and std.mean. The user must either qualify the vendor folds or import them with distinct aliases:


using vendor.Stats as stats;
using vendor.Stats { count as statsCount, avg as statsMean };

items.Σcount       // std.count
items.Σmean        // std.mean
items.Σstats.count // vendor.Stats.count
items.Σstats.avg   // vendor.Stats.avg
items.ΣstatsCount  // vendor.Stats.count
items.ΣstatsMean   // vendor.Stats.avg

This rule keeps existing source stable when new libraries are imported: adding a third-party component cannot silently change the meaning of an existing standard fold such as Σcount.

Names that are not standard prelude fold names remain available to user components. A component may declare a fold named median, collapse, or any other non-standard local name, subject to the usual declaration and import rules. An unqualified use such as items.Σmedian is valid only when it resolves to such a visible declaration; otherwise it is an unresolved fold name.