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.