Examples¶
Clausal Prolog ships with example programs in clausal/examples/. Each is a self-contained seam (.seam) module demonstrating different language features.
Seam vs Prolog syntax
Seam and Prolog syntax may slightly differ — for example, variables are
ALLCAPS, rules use <- instead of :-, and lists are Python-style. Keep
this in mind when comparing with Prolog resources.
Clausal Prolog (.clausal) uses ISO Prolog syntax instead.
You can also import Prolog .pl files directly without rewriting them.
Basics¶
fibonacci.seam¶
Classic Fibonacci sequence with pattern-matching base cases:
See: Tabling, Arithmetic builtins
peano.seam¶
Peano arithmetic: natural number representation, addition, multiplication, and ordering via structural recursion.
graph.seam¶
Graph traversal: path/3 (path finding with cycle detection), reachable/2, and connected/2 over edge facts.
Algorithms¶
sorting.seam¶
Two sorting algorithms:
naive_sort/2— permutation sort (generate-and-test)qsort/2— quicksort with partition
See: List builtins
nqueens.seam¶
N-Queens puzzle using permutation-based search: numlist, permutation, safe/1, and no_attack/3 diagonal constraint checking.
See: List builtins
hanoi.seam¶
Tower of Hanoi: generates the sequence of moves to solve the puzzle for N disks.
Symbolic Computation¶
symbolic_diff.seam¶
Symbolic differentiation: diff(EXPR, VAR, DERIV) computes the derivative of an algebraic expression with respect to a variable. Handles constants, variables, addition, multiplication, power, and chain rule.
Constraint Satisfaction¶
sudoku.seam¶
Classic Sudoku solver using CLP(ℤ) constraints, ported from Markus Triska's sudoku.pl. Posts row, column, and 3×3 block all_different constraints, then labels. Includes three sample puzzles.
sudoku(ROWS) <- (
ROWS is [R1, R2, R3, R4, R5, R6, R7, R8, R9],
flatten(ROWS, VS),
in_domain(VS, 1, 9),
maplist(all_different, ROWS),
transpose(ROWS, COLUMNS),
maplist(all_different, COLUMNS),
blocks(R1, R2, R3), blocks(R4, R5, R6), blocks(R7, R8, R9)
)
Features: nested star-list patterns ([[HEAD, *TAIL], *ROWS]), builtin predicates as higher-order arguments (maplist(all_different, ...)), recursive transpose.
See: CLP(ℤ), Higher-order predicates, Meta-predicates
map_coloring.seam¶
Four-color map coloring: given a map of regions and adjacency constraints, finds valid colorings using forall/2 and is not (structural disequality).
See: Meta-predicates
Higher-Order & Lambdas¶
lambdas.seam¶
Lambda (goal closure) examples: apply_val, add_one, add_z, double_val, and more. Demonstrates variable capture, multi-arg closures, and conjunction bodies.
See: Lambdas
higher_order.seam¶
Higher-order list predicates: doubles (maplist/3), all_positive (maplist/2), keep_positive (include/3), remove_negative (exclude/3), and sum_list_fold (foldl/4).
meta_predicates.seam¶
Meta-predicate examples: squares (findall/3), bag_positives (bagof/3), unique_members (setof/3), all_positive (forall/2).
See: Meta-predicates
Meta-interpreters¶
metainterpreters.seam¶
Five meta-interpreters ported from Markus Triska's A Couple of Meta-interpreters in Prolog. Object-level programs are represented as lists of [HEAD, BODY] clause pairs of ordinary terms ([natnum(succ(X)), [natnum(X)]]). copy_term/2 provides fresh variable copies at each resolution step.
solve/2 — vanilla list-based meta-interpreter (tail-recursive). Resolves goals against an explicit program:
solve([], _PROGRAM_UNUSED),
solve([GOAL, *GOALS], PROGRAM) <- (
match_clause(GOAL, BODY, PROGRAM),
append(BODY, GOALS, ALL_GOALS),
solve(ALL_GOALS, PROGRAM)
)
match_clause(GOAL, FRESH_BODY, PROGRAM) <- (
in_(CLAUSE, PROGRAM),
copy_term(CLAUSE, [FRESH_HEAD, FRESH_BODY]),
GOAL is FRESH_HEAD
)
solve_count/3 — counts inference steps:
solve_count([], _PROGRAM_UNUSED, 0),
solve_count([GOAL, *GOALS], PROGRAM, COUNT) <- (
match_clause(GOAL, BODY, PROGRAM),
append(BODY, GOALS, ALL_GOALS),
solve_count(ALL_GOALS, PROGRAM, SUB_COUNT),
COUNT == SUB_COUNT + 1
)
solve_limit/3 — depth-limited search. Each clause resolution consumes one unit of depth:
solve_limit([], _PROGRAM_UNUSED, _MAX_UNUSED),
solve_limit([GOAL, *GOALS], PROGRAM, MAX) <- (
MAX > 0,
MAX1 == MAX - 1,
match_clause(GOAL, BODY, PROGRAM),
append(BODY, GOALS, ALL_GOALS),
solve_limit(ALL_GOALS, PROGRAM, MAX1)
)
solve_iterative_deepening/2 — complete search via increasing depth limits. Finds solutions even in cyclic programs where naive DFS diverges:
solve_iterative_deepening(GOALS, PROGRAM) <- (
between(0, 1000, DEPTH),
solve_limit(GOALS, PROGRAM, DEPTH)
)
solve_tree/3 — builds explicit proof trees. Each node is [Goal, [subtrees...]]:
solve_tree([], _PROGRAM_UNUSED, []),
solve_tree([GOAL, *GOALS], PROGRAM, [[GOAL, BODY_TREE], *GOALS_TREE]) <- (
match_clause(GOAL, BODY, PROGRAM),
solve_tree(BODY, PROGRAM, BODY_TREE),
solve_tree(GOALS, PROGRAM, GOALS_TREE)
)
Three sample programs are included: natural numbers (natnum_program), an acyclic graph (graph_program), and a cyclic graph (cyclic_program) that demonstrates iterative deepening's advantage over plain DFS.
See: Meta-Interpreters tutorial, Builtins (copy_term, in_, append, between)
DCGs¶
dcg_state.seam¶
DCG state threading patterns: counter (inc, count3), tree leaf counting (count_leaves, num_leaves), and accumulator (push, push_all, collect_items).
See: DCGs
Running Examples¶
Add test predicates to any example file, then run with pytest:
Or query from Python. In a .seam
file, write the goal in goal position:
# fib_report.seam
-import_module(clausal.examples.fibonacci)
def fib(n):
for F in --clausal.examples.fibonacci.fib(++n, F):
return F
import clausal, fib_report; fib_report.fib(10) is 55. From a plain .py
file, build the goal cell and run it against the module: