Foreign Functions
While there are existing foreign functions such as $hash
and $abs
, people sometimes want more functions to be included for specialized computation.
scallopy
provides such interface and allows user to define foreign functions in Python.
Here is an example defining a custom $sum
function in Python which is later used in Scallop:
# Create a new foreign function by annotating an existing function with `@scallopy.foreign_function`
# Note that this function has variable arguments!
@scallopy.foreign_function
def my_sum(*args: int) -> int:
s = 0
for x in args:
s += x
return s
# Create a context
ctx = scallopy.ScallopContext()
# Register the declared foreign function (`my_sum`)
# Note that the function needs to be registered before it is used
ctx.register_foreign_function(my_sum)
# Add some relations
ctx.add_relation("I", (int, int))
ctx.add_facts("I", [(1, 2), (2, 3), (3, 4)])
# Add a rule which uses the registered function!
ctx.add_rule("R($my_sum(a, b)) = I(a, b)")
# Run the context
ctx.run()
# See the result, should be [(3,), (5,), (7,)]
print(list(ctx.relation("R")))
Now we elaborate on how we define new foreign functions in Python.
Function Signature
The annotator @scallopy.foreign_function
performs analysis of the annotated Python function and makes sure that it is accepted as a Scallop foreign function.
We require that types are annotated on all arguments and the return value.
For simplicity, Python types such as int
, bool
, and str
are mapped to Scallop types (and type families) as following:
Python type | Scallop type | Scallop base types |
---|---|---|
int | Integer family | i8 , i16 , ..., u8 , u16 , ..., usize |
float | Float family | f32 , f64 |
bool | bool | bool |
str | String | String |
If one desires to use a more fine-grained type