1 microKanren
| (require typed/microKanren/amb) | package: ambKanren |
This module is microKanren (Hemann and Friedman, μKanren: A Minimal Functional Core for Relational Programming, Scheme Workshop 2013) with its streams replaced by amb. It follows typed/microKanren of the miniKanren-typed package, the Typed Racket rewrite of the code at https://github.com/jasonhemann/microKanren, definition by definition; the definitions that only exist to manipulate streams are gone.
1.1 From Streams to amb
In microKanren, a goal returns a stream of states: every answer at once, lazily. The stream type is a monad, and the connectives are its operations. With amb, the nondeterminism is an effect of evaluation rather than a value, so it disappears from the type of goals: a goal returns a single state, chooses among its answers with amb, and fails by calling (amb).
|
| |||
|
| |||
success |
| (unit s/c) |
| s/c |
failure |
|
| (amb) | |
| (mplus (g1 s/c) (g2 s/c)) |
| ((amb g1 g2) s/c) | |
| (bind (g1 s/c) g2) |
| (g2 (g1 s/c)) | |
|
| |||
| force and collect the stream (g empty-state) |
| collect (in-amb/do (g empty-state)) |
So success returns the state unchanged, conjunction is plain function composition, and disjunction is a choice made by amb. The monadic structure has not gone away: it now lives in the continuation captured by amb, and in-amb/do is what turns that control effect back into a sequence of answers.
The definitions that remain are those of typed/microKanren, with these changes:
unit, mzero, mplus, bind, pull, and the stream types are removed.
take and take-all take a thunk that performs the nondeterministic computation, instead of a stream, and call/goal returns a state.
1.1.1 Suspension and the Order of Answers
In microKanren, Zzz wraps a goal so that it returns an immature stream, and mplus swaps its two streams whenever the first one is immature; this is what lets a disjunction leave a branch that never produces an answer. Here, Zzz calls suspend, which lets the computations already waiting in amb’s frontier run first:
> (: relo (→ Term Goal)) > (define (relo x) (fresh (a d) (== x `(,a . ,d)) (relo x))) > (run 1 (x) (disj+ (relo '(5 . 6)) (== x 3))) - : (Listof Term)
'(3)
The two schedules produce the same answers but not always in the same order. mplus swaps a suspended stream only with the other side of the disjunction it belongs to, while suspend sends the computation to the back of a single, global frontier, which is closer to breadth-first search. All the tests of microKanren-test.scm give the same results as microKanren; of the examples of miniKanren-wrappers.scm, the two that use rember*o return their answers in a different order.
1.2 Types
type
type
type
> ((== 1 1) empty-state) - : State
'(() . 0)
> ((call/fresh (λ (q) (== q 5))) empty-state) - : State
(cons (list (cons (var 0) 5)) 1)
> (take-all (λ () ((call/fresh (λ (q) (disj (== q 5) (== q 6)))) empty-state))) - : (Listof State)
(list (cons (list (cons (var 0) 5)) 1) (cons (list (cons (var 0) 6)) 1))
1.3 The Core
procedure
(call/fresh f) → Goal
f : (→ Var Goal)
> (take-all (λ () ((conj (call/fresh (λ (a) (== a 7))) (call/fresh (λ (b) (disj (== b 5) (== b 6))))) empty-state))) - : (Listof State)
(list
(cons (list (cons (var 1) 5) (cons (var 0) 7)) 2)
(cons (list (cons (var 1) 6) (cons (var 0) 7)) 2))
procedure
u : Term s : Substitution
procedure
(ext-s x v s) → Substitution
x : Var v : Term s : Substitution
procedure
(unify u v s) → (Option Substitution)
u : Term v : Term s : Substitution
1.4 User-Level Forms
These are the forms of miniKanren-wrappers.scm.
syntax
(Zzz goal)
syntax
(conj+ goal ...+)
syntax
(disj+ goal ...+)
syntax
(fresh (x ...) goal ...+)
syntax
(conde [goal ...+] ...+)
> (: appendo (→ Term Term Term Goal))
> (define (appendo l s out) (conde [(== '() l) (== s out)] [(fresh (a d res) (== `(,a . ,d) l) (== `(,a . ,res) out) (appendo d s res))])) > (run* (x y) (appendo x y '(1 2 3))) - : (Listof Term)
'(() (1) (1 2) (1 2 3))
procedure
s/c : State
procedure
v : Term s : Substitution
procedure
(reify-s v s) → Substitution
v : Term s : Substitution
procedure
(reify-name n) → Symbol
n : Natural