Our PL reading group read the paper “μKanren: A Minimal Functional Core for Relational Programming” this week. It presents a minimalist logic programming language in Scheme in 39 lines of code. Since none of us are really Schemers, a bunch of us quickly set about porting the code to our personal pet languages. Chris Martens produced this SML version. I hacked up a version in Haskell.
The most interesting part about this was the mistake I made in the initial version. To deal with recursion and potentially infinite search trees, the Scheme version allows some laziness; streams of results can be functions that delay search until forced; when a Scheme μKanren program wants to create a recursive relation it needs wrap the recursive call in a dummy function (and plumb through the input state); the Scheme version wraps this in a macro called Zzz
to make doing it more palatable. I originally thought that all of this could be dispensed with in Haskell; since Haskell is lazy, no special work needs to be done to prevent self reference from causing an infinite loop. It served an important secondary purpose, though: providing a way to detect recursion so that we can switch which branch of the tree we are exploring. Without this, although the
The initial version was also more generalized. The type signatures allowed for operating over any MonadPlus
, thus allowing pluggable search strategies. KList
was just a newtype wrapper around lists. When I had to add delay
I could have defined a new MonadPlusDelay
typeclass and parametrized over that, but it didn’t’ seem worthwhile.
A mildly golfed version that drops blank lines, type annotations, comments, aliases, and test code clocks in at 33 lines.