Skip to content
An implementation of microKanren for Pony.
Pony Batchfile Makefile
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
kanren
.gitignore
CONTRIBUTING.md
LICENSE
Makefile
README.md
STYLE_GUIDE.md
VERSION
bundle.json
make.bat

README.md

Pony-Kanren

Pony-Kanren is an implementation of microKanren for the Pony programming language.

The easiest way to use Pony-Kanren in your code is via Pony-Stable: run

stable add github kulibali/pony-kanren

to add Pony-Kanren as a dependency to your bundle.json, and then

use "kanren"

in your code to import the library.

You can find library documentation here.

Workflow

To set up a logic expression and query its results:

  • Create an empty State value, with a functor that can unify the data type that your variables refer to.
  • Create a Goal that represents a logical expression.
    • Use the Goal.fresh() function to obtain a new state that knows about a variable. That variable will now be visible to subgoals. Note that if you use Goal.fresh() more than once, the variables will be disjoint. If their scopes intersect, you will get errors.
    • Use Goal.conj() for the logical AND operation. This will succeed only if both its subgoals succeed.
    • Goal.disj() is logical OR. This will succeed if either of its subgoals succeeds.
    • Goal.unify_vars() will unify two variables, if possible.
    • Goal.unify_vals() will attempt to structurally unify two values.
    • Goal.unify_val() will bind a variable to a value, if possible.
  • A goal is a function that returns a sequence of states. Each state may contain variable bindings that represent a solution to the logical expression.
    • If there is no solution for the expression, the sequence will be empty.
    • If an error occurrs when solving, the sequence will contain a solution with unbound variables and some error messages obtainable via its get_errors() method.
  • You can query the value of any variable in a particular state using the state's apply() method.

Example

The following Pony code initializes and solves the expression A = B && (B = 123 || B = 456). Running the goal will result in a sequence of two states, one where A and B are bound to 123, and one where A and B are bound to 456:

use "kanren"

let a = Var("A")
let b = Var("B")
let g =
  Goals.fresh[USize](a,
    Goals.fresh[USize](b,
      Goals.conj[USize](
        Goals.unify_vars[USize](b, a),
        Goals.disj[USize](
          Goals.unify_val[USize](b, 123),
          Goals.unify_val[USize](b, 456)
        ))))

let results = g(State[USize](UnifyEq[USize]))
let s1 = results.next()?
s1(a) == 123 // true
s1(b) == 123 // true
let s2 = results.next()?
s2(a) == 456 // true
s2(b) == 456 // true
You can’t perform that action at this time.