1 min read

MiniKanren and Colonel Mustard

So, a friend posted up his functional version of a challenge. The first thing I thought was how this would be a great thing to encode into a Logic programming language. Of course, I chose minikanren, and the following code demonstrates the idea:

(import (chezscheme) (minikanren definitions) (minikanren vanilla))

(define (listo lst . args)
(if (null? args)
(nullo lst)
(exist (t1)
(conso (car args) t1 lst)
(apply listo (cons t1 (cdr args))))))

(define (make-theory s w r)
(lambda (gs gw gr)
(exist ()
(== gs s)
(== gw w)
(== gr r))))

(define (solve-murder theoryo)
(run1 (x)
(exist (a b c suspects weapons rooms)
(== suspects
'(miss-scarlett colonel-mustard mrs-white
the-reverend-green mrs-peacock professor-plum))
(== weapons
'(dagger candlestick revolver rope lead-pipe spanner))
(== rooms
'(kitchen ballroom conservatory dining-room cellar
billiard-room library lounge hall study))
(membero a suspects)
(membero b weapons)
(membero c rooms)
(listo x a b c)
(theoryo a b c))))

(define theoryo (make-theory 'colonel-mustard 'revolver 'library))

(display (car (solve-murder theoryo)))

Of course, there is a problem in this solution; it will do a huge search instead of indicating what things to try next. But that's kind of the point. I don't know if you could do this more efficiently using minikanren, and maybe you could, but the basic coolness of logic programming is that such things are taken care of in the backend. The important thing to note here is that I didn't actually have to program any logic or program flow. All I did was make some declarations which pretty much mirror the problem description, and out comes an answer. Very fun. :)

Anyone who wants to comment on my friend's functional version should do so as well, to help out someone who is learning his way through functional programming.