Make sure you have the miniKanren implementation with never-equalo:
#f
(+ 5 6)
(if (zero? 0) (+ 5 4) (sub1 8))
(lambda (x) (+ x x))
(lambda (x) (lambda (y) (+ x y)))
(lambda (x) (lambda (y) (zero? (y (sub1 x)))))
(if ((lambda (x) #t) 9) 5 8)
((lambda (x) x) (+ 5 7))
((lambda (x) (sub1 x)) ((lambda (y) (+ 5 ((lambda (z) z) 6))) 8))
(car (cons (cons 3 4) #t))
fix
zero?
sub1
car, cdr, and cons. This will
require you to introduce the pair type.
lookup helper relation, described below.
Your inferencer should pass all of the tests at the bottom of the file.
Each test should terminate in under ten seconds when using Petite Chez
Scheme. Remember to choose the ordering of your goals carefully (for example,
calls to == should come before calls to recursive goals).
lookuplookup helper relation is similar to the apply-env function used in your interpreter.
apply-env looks up the value of a variable in an environment, which we might represent as an association list:(apply-env 'x '((x . 5) (y . 6) (x . 3)) => 5.lookup relation succeeds when
x appears in the type environment gamma, associating x
with some type t:(run* (q) (lookup 'y '((y . bool) (z . int) (y . int)) q)) => (bool)y appears twice in the type environment, the run* expression
returns (bool) instead of (bool int).
In order words, lookup must handle variable shadowing.
lookup, you might begin by translating the apply-env function
into miniKanren, using the transformations from the previous assignment.
letrec to your type inferencer. To simplify the problem, assume that the right-hand-side of each letrec binding is a lambda expression of one argument.
let to your type inferencer. Polymorphic let is described in Exercise 7.28 on page 273 of Essentials.