Module Flambda2_datalog.Datalog
Well-typed Datalog implementation.
module Column : sig ... endDatalog tables are represented as a nesting of multiple maps; for instance, a binary relation on integers is represented as a unit Int.Map.t Int.Map.t.
val create_table :
?provenance:bool ->
name:string ->
default_value:'v ->
('t, 'k, 'v) Flambda2_datalog.Datalog.Column.hlist ->
('t, 'k, 'v) Flambda2_datalog.Datalog.tableThe provenance argument is true by default. If set to false, provenance tracking will be disabled for this table. This is useful for derived tables that are defined by a single rule, such as indices defined by a permutation of another table.
val columns :
('t, 'k, 'v) Flambda2_datalog.Datalog.table ->
('t, 'k, 'v) Flambda2_datalog.Datalog.Column.hlisttype ('t, 'k) relation = ('t, 'k, unit) Flambda2_datalog.Datalog.tableval create_relation :
?provenance:bool ->
name:string ->
('t, 'k, unit) Flambda2_datalog.Datalog.Column.hlist ->
('t, 'k) Flambda2_datalog.Datalog.relationcreate_relation ~name schema creates a new relation with name name and schema schema.
The schema is given as a heterogenous list of column types, and the relation is represented in memory as a series of nested maps following this list. If the schema ty1; ty2; ty3 is provided, the relation will be represented as a map from ty1 whose values are maps from ty2 to ty2. The order of arguments provided to a relation thus have profound implication for the performance of iterations on the relation, and needs to be chosen carefully.
See documentation of create_table for the provenance argument.
Example
The following code defines a binary edge relationship between nodes, represented as a map from a node to its successors, and an unary predicate to distinguish some sort of marked nodes.
let marked_pred : node rel1 =
create_relation ~name:"marked" [node]
let edge_rel : (node, node) rel2 =
create_relation ~name:"edge" [node; node]module Constant : sig ... endThe Constant module only provides a heterogenous list to represent lists of values.
module Term : sig ... endtype hypothesis = [ | `Atom of Flambda2_datalog.Datalog.atom| `Not_atom of Flambda2_datalog.Datalog.atom| `Distinct of Flambda2_datalog.Datalog.equality| `Filter of Flambda2_datalog.Datalog.filter
]val atom :
('t, 'k) Flambda2_datalog.Datalog.relation ->
'k Flambda2_datalog.Datalog.Term.hlist ->
[> `Atom of Flambda2_datalog.Datalog.atom ]atom rel args represents the application of relation rel to the arguments args.
When writing queries or rules, it can be helpful to partially apply atom to relations in order to improve readability.
Example
let marked = atom marked_pred
let edge = atom edge_relval not :
[< `Atom of Flambda2_datalog.Datalog.atom ] ->
[> `Not_atom of Flambda2_datalog.Datalog.atom ]val distinct :
(_, 'k, _) Flambda2_datalog.Datalog.Column.id ->
'k Flambda2_datalog.Datalog.Term.t ->
'k Flambda2_datalog.Datalog.Term.t ->
[> `Distinct of Flambda2_datalog.Datalog.equality ]val filter :
('k Flambda2_datalog.Datalog.Constant.hlist -> bool) ->
'k Flambda2_datalog.Datalog.Term.hlist ->
[> `Filter of Flambda2_datalog.Datalog.filter ]val print :
Stdlib.Format.formatter ->
Flambda2_datalog.Datalog.database ->
unitval empty : Flambda2_datalog.Datalog.databaseval get_table :
('t, 'k, 'v) Flambda2_datalog.Datalog.table ->
Flambda2_datalog.Datalog.database ->
'tval set_table :
('t, 'k, 'v) Flambda2_datalog.Datalog.table ->
't ->
Flambda2_datalog.Datalog.database ->
Flambda2_datalog.Datalog.databaseval add_fact :
('t, 'k) Flambda2_datalog.Datalog.relation ->
'k Flambda2_datalog.Datalog.Constant.hlist ->
Flambda2_datalog.Datalog.database ->
Flambda2_datalog.Datalog.databaseadd_fact rel args db records a fact into the database db.
Example
The following code populates a database with a small graph and a single marked node n1.
let n1 = Node.make ()
let n2 = Node.make ()
let n3 = Node.make ()
let n4 = Node.make ()
let n5 = Node.make ()
let db =
add_fact marked_pred [n1]
@@ add_fact edge_rel [n1; n2]
@@ add_fact edge_rel [n3; n2]
@@ add_fact edge_rel [n2; n5]
@@ add_fact edge_rel [n5; n4]
@@ add_fact edge_rel [n4; n2]
@@ emptymodule String : sig ... endPseudo-heterogenous lists of strings.
module Cursor : sig ... endA cursor represents a query on the database. Cursors provide iter and fold functions to iterate over the matching facts.
The type of compiled rules.
Rule specifications must be compiled to low-level rules using compile_rule before being applied to a database using Schedule.rules.
Note: Although compiled rules are mutable data structures, this mutability is only exploited while the compiled rule is executing (e.g. during Schedule.run). It is thus safe to reuse a rule across multiple schedules or within the same schedule.
module Schedule : sig ... endval print_bindings :
Stdlib.Format.formatter ->
Flambda2_datalog.Datalog.bindings ->
unitThe type ('p, 'v) program is the type of programs returning values of type 'v with parameters 'p.
The output of programs is either queries or rules; the use of a shared types allows writing combinators that work in both cases.
val compile :
'v Flambda2_datalog.Datalog.String.hlist ->
('v Flambda2_datalog.Datalog.Term.hlist ->
(Flambda2_datalog.Datalog.nil, 'a) Flambda2_datalog.Datalog.program) ->
'aCompile a program and returns the resulting value.
Note: As a convenience, compile takes a list of variables and binds them immediately with foreach. To compile an existing program with no free variables, use compile [] (fun [] -> program).
Repeated compilation of a program building mutable values (such as cursors) create new values each time they are compiled.
val compile_with_parameters :
'p Flambda2_datalog.Datalog.String.hlist ->
'v Flambda2_datalog.Datalog.String.hlist ->
('p Flambda2_datalog.Datalog.Term.hlist ->
'v Flambda2_datalog.Datalog.Term.hlist ->
('p, 'a) Flambda2_datalog.Datalog.program) ->
'aval foreach :
'a Flambda2_datalog.Datalog.String.hlist ->
('a Flambda2_datalog.Datalog.Term.hlist ->
('p, 'b) Flambda2_datalog.Datalog.program) ->
('p, 'b) Flambda2_datalog.Datalog.programforeach vars prog binds the variables vars in prog.
The order variables are provided in vars is the iteration order during evaluation.
val where :
Flambda2_datalog.Datalog.hypothesis list ->
('p, 'a) Flambda2_datalog.Datalog.program ->
('p, 'a) Flambda2_datalog.Datalog.programval yield :
'v Flambda2_datalog.Datalog.Term.hlist ->
('p, ('p, 'v) Flambda2_datalog.Datalog.Cursor.with_parameters)
Flambda2_datalog.Datalog.programyield args is a query program that outputs the tuple args.
type deduction = [ | `Atom of Flambda2_datalog.Datalog.atom| `And of Flambda2_datalog.Datalog.deduction list
]val deduce :
Flambda2_datalog.Datalog.deduction ->
(Flambda2_datalog.Datalog.nil, Flambda2_datalog.Datalog.rule)
Flambda2_datalog.Datalog.programdeduce rel args adds the fact rel args to the database.
module Schema : sig ... end