LeanElpi

Types and modes

ELPI is typed. Types catch most mistakes before a program runs, and they let the engine pick the right overload and print errors early.

Kinds and constructors

kind nat type.
type z nat.
type s nat -> nat.

kind declares a new type. type declares a constructor or constant with its type. Several constants can share a declaration: type ann, bob, carl person.

Predicates and modes

pred plus i:nat, i:nat, o:nat.
plus z N N.
plus (s M) N (s R) :- plus M N R.

pred declares a predicate, its argument types, and a mode for each argument:

Modes are not just documentation. For an input argument the engine matches the clause head against the call instead of unifying, so a call with a still-unknown input does not silently bind it. They also guide indexing, which makes clause selection fast.

With these declarations, plus (s (s z)) (s z) R gives R = s (s (s z)).

Polymorphism

Type variables are uppercase. pred append i:list A, i:list A, o:list A. works on any element type. Type checking infers and checks the instances at each use.

Errors you will see

A misuse is reported with a position before anything runs:

Two kinds of "mode"

If you also use the LF layer, note that its #mode directive is a different thing. ELPI's i:/o: changes how the engine runs a predicate. The LF #mode plus +N +M -P is a static check that inputs are ground, and it never changes execution. The LF chapter covers it.