Microkanren
microKanren in python
Install / Use
/learn @ethframe/MicrokanrenREADME
microkanren
Yet another microkanren implementation in Python. Still work in progress.
Features:
- Lists and namedtuples unification
- Disequality constraints
- Type constraints
- Reasonably fast non-relational arithmetic
Examples
Bruteforce factorization
from mk.arithmetic import add, lte, mul
from mk.core import disj, eq
from mk.dsl import conjp, delay, fresh
from mk.run import run
from mk.unify import Var
@delay
def numbers(a, b, out):
return disj(
eq(a, out),
fresh(lambda n: conjp(
add(a, 1, n),
lte(n, b),
numbers(n, b, out)
))
)
a = Var()
b = Var()
goal = conjp(
numbers(0, 256, a),
mul(a, b, 65535)
)
print(list(run(0, (a, b), goal)))
# [(1, 65535), (3, 21845), (5, 13107), (15, 4369),
# (17, 3855), (51, 1285), (85, 771), (255, 257)]
Lisp-like language interpreter (without auxiliary code)
Full source with quines generation: examples/lisp_interpreter.py
from mk.core import eq, eqt
from mk.dsl import conde, conjp, delay, fresh
from mk.ext.lists import no_item
@delay
def eval_expr(exp, env, out):
return conde(
# Quoted value - 'a
(eq([quote, out], exp), no_item(out, is_closure), missing(quote, env)),
# List constructor - (list a b c)
fresh(lambda lst: conjp(
eq([list_, lst, ...], exp),
missing(list_, env), eval_list(lst, env, out),
)),
# Function call - (fn a)
fresh(4, lambda var, body, cenv, arg: conjp(
eval_list(exp, env, [Closure(var, body, cenv), arg]),
eval_expr(body, Env(var, arg, cenv), out),
)),
# Function definition - (lambda (x) body)
fresh(2, lambda var, body: conjp(
eq([lambda_, [var], body], exp), eq(Closure(var, body, env), out),
eqt(var, Symbol), missing(lambda_, env),
)),
# Variable reference - a
(eqt(exp, Symbol), lookup(exp, env, out)),
)
API summary
Goal constructors
mk.core
eq(a, b)- construct goal that succeeds whenacan be unified withbeqt(a, b)- construct goal that succeeds when type ofacan be unified withbdisj(goal_1, goal_2)- construct composite goal that succeeds whengoal_1orgoal_2succeedconj(goal_1, goal_2)- construct composite goal that succeeds when bothgoal_1andgoal_2succeed
mk.disequality
neq(a, b)- negation ofeq(a, b)neqt(a, b)- negation ofeqt(a, b)
mk.arithmetic
add(a, b, c)- construct goal that succeeds whena + b == csub(a, b, c)- construct goal that succeeds whena - b == cmul(a, b, c)- construct goal that succeeds whena * b == cdiv(a, b, c)- construct goal that succeeds whena // b == cgte(a, b)- construct goal that succeeds whena >= blte(a, b)- construct goal that succeeds whena <= b
mk.dsl
disjp(goal, ...)- n-arydisjconjp(goal, ...)- n-aryconjconde((goal, ...), (goal, ...), ...)- shortcut fordisjp(conjp(goal, ...), conjp(goal, ...), ...)
mk.ext.lists
no_item(a, predicate)- construct goal that fails whenais list that contains item, possibly in nested list, for whichpredicateis true.
mk.ext.tuples
no_item(a, predicate)- construct goal that fails whenais tuple that contains item, possibly in nested tuple, for whichpredicateis true.
Goal helpers
mk.dsl
@delay(goal_constructor)- decorator for recursive goal constructorsfresh(goal_constructor)- constructs goal that callsgoal_constructorwith fresh variablefresh(n, goal_constructor)- constructs goal that callsgoal_constructorwithnfresh variables
Running goals
mk.run
run(n, query, goal)- rungoal, apply resulting substitution toquery, takenfirst results
Related Skills
node-connect
354.2kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
claude-opus-4-5-migration
112.2kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
frontend-design
112.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
model-usage
354.2kUse CodexBar CLI local cost usage to summarize per-model usage for Codex or Claude, including the current (most recent) model or a full model breakdown. Trigger when asked for model-level usage/cost data from codexbar, or when you need a scriptable per-model summary from codexbar cost JSON.
