Foreign Predicates

Foreign predicates aim to provide programmers with extra capabilities with relational predicates. Traditional Datalog program defines relational predicate using only horn-rules. Given the assumption that the input database is finite, these derived relational predicates will also be finite. However, there are many relational predicates that are infinite and could not be easily expressed by horn-rules. One such example is the range relation. Suppose it is defined as range(begin, end, i) where i could be between begin (inclusive) and end (exclusive). There could be infinitely many triplets, and we cannot simply enumerate all of them. But if the first two arguments begin and end are given, we can reasonably enumerate the i.

In Scallop, range is available to be used as a foreign predicate. Notice that range can be applied on any integer data, making it a generic predicate. For example, to use range on i32 data, we will need to invoke range<i32>:

rel result(x) = range<i32>(0, 5, x)

Here we enumerate the value of x from 0 (inclusive) to 5 (exclusive), meaning that we will obtain that result = {0, 1, 2, 3, 4}. For the rest of this section, we describe in detail how foreign predicates are constructed in Scallop and why are they useful.

Foreign Predicate Types

Foreign predicates can be generic and are statically typed. In addition to just providing the argument types, we also need to provide a boundness pattern.

A boundness pattern is a string of length equal to the relation arity and consisting of b and f. The character b means bounded, reflecting the variable on that position is taken as input to the predicate. The character f means free, suggesting that the variable on that position will be generated as output by the predicate.

For example, the full definition of range is

range<T: Integer>(begin: T, end: T, i: T)[bbf]

Notice that at the end of the definition we have [bbf]. Here, bbf is a boundness pattern for range, suggesting that begin and end will be provided as input, and i will be generated as output.

In the future, we plan to allow the definition of multiple boundness patterns

Standard Library of Foreign Predicates (Part A)

In this part, we give an overview to the foreign predicates that are discrete only.

Foreign PredicateDescription
datetime_ymd(d: DateTime, y: i32, m: u32, d: u32)[bfff]Get the year, month, and day from a DateTime value
range<T: Integer>(begin: T, end: T, i: T)[bbf]Generate all the integers i starting from begin and end with end - 1
string_chars(s: String, i: usize, c: char)[bff]Generate all the index-character tuples inside of string s
string_find(s: String, pat: String, begin: usize, end: usize)[bbff]Generate all the begin-end ranges of the pattern pat's occurrence in the string s
string_split(s: String, pat: String, out: String)[bbf]Split the string s using the pattern pat and generate the out strings