Iterative miniKanren in multiple languages

Motivation

The Codex Bezae is an ancient-era handwritten book where each left-side page of Greek has a translation into Latin on the right-side page. It is digitized at https://cudl.lib.cam.ac.uk/view/MS-NN-00002-00041. It was immensely helpful for me when I was studying Greek and Latin. The Biblical vocabulary and grammar was plain and I had two translations to work with.

I want to do something similar with this project. I hope you can learn something from similar code written in multiple programming languages.

Since this document is read from top to bottom by the Bezae compiler, all import statements must be included first.

What is an S-Expression?

An S-Expression (here on referred to as a SExp) is either an atom, or a pair. All atoms will be represented as a symbol, and for most languages, a symbol is just a string. The pair case of SExp is more complicated, because it contains two SExps as children. S-Expressions come from Lisp, and in Lisp, this pair case is called a cons pair, where the left child is called car and the right child is called cdr.

Does the symbol occur anywhere in the SExp?

Given: a Symbol and a SExp, returns true if the SExp contains the same symbol (that is, a string with the same contents).

Replace symbol in a SExp

Given a symbol, an s-expression replacement, and an s-expression body, returns a new s-expression body with all occurrences of the symbol replaced with the s-expression.

miniKanren and the definition of a clause

For my purposes, the definition of a miniKanren clause is best described in Haskell:

Replace symbol with s-expression in a miniKanren clause

Given a symbol, an SExp to replace it with, and a miniKanren clause, produce a new clause with all occurrences of the symbol replaced with the s-expression. But it must also respect lexical scope: if a fresh clause defines an identical symbol, do not replace in the fresh body, because the symbol has been shadowed.

defrel, run, and run*

The final pieces of miniKanren syntax allow us to define and run relations.

The appendo relation

Having defined all the miniKanren keywords, I can now write the classic appendo relation.