1 microKanren
| (require typed/microKanren) | package: miniKanren-typed |
This module is a Typed Racket rewrite of microKanren (Hemann and Friedman, μKanren: A Minimal Functional Core for Relational Programming, Scheme Workshop 2013), from the code at https://github.com/jasonhemann/microKanren: the core of microKanren.scm and the user-level forms of miniKanren-wrappers.scm. The core is a handful of functions over states and streams; everything else is defined on top of them.
The differences from that code are:
Types. Every definition has a type.
Variables. A variable is a struct holding its counter, (var 0), rather than the vector #(0), so that variables are distinguished from the other values of a term.
Literals. Literals are compared with equal? rather than eqv?, as in the other modules of this package.
Stream operations. The representation of streams is the paper’s, but mplus, bind, and Zzz reach it only through a few operations (stream-first, stream-rest, stream-cons, and so on), which read a suspension as an element pause. The same operations are used by typed/miniKanren/trs2. The paper’s mzero and unit are empty-stream and stream, and its pull, take, and take-all are stream-force, stream-force-take, and stream->list, named after racket/stream.
1.1 Types
type
type
type constructor
(Streamof a)
type constructor
(Suspension a)
(define-type (Streamof a) (∪ Null (Pair a (Streamof a)) (Suspension a))) (define-type (Suspension a) (→ (Streamof a)))
A stream is empty, or an answer followed by a stream (mature), or a suspension that produces a stream when called (immature). Read element by element, a suspension is a pause followed by the stream it produces, so a stream is a lazy list of (Maybe a).
type
> ((== 1 1) empty-state) - : (Streamof State)
'((() . 0))
> ((call/fresh (λ (q) (== q 5))) empty-state) - : (Streamof State)
(list (cons (list (cons (var 0) 5)) 1))
1.2 Streams
The definitions of this section are the only code that knows how Streamof is represented. They read a stream element by element, a suspension being the element pause; the rest of the code, mplus and bind included, is written with them.
1.2.1 Pauses
1.2.2 Constructing Streams
value
syntax
(stream a ...)
syntax
(stream-cons a d)
(stream-cons pause d)
syntax
(stream-lazy d)
1.2.3 Reading Streams
procedure
(stream-empty? $) → Boolean
$ : (Streamof a)
procedure
(stream-first $) → a
$ : (Pair a (Streamof a)) (stream-first $) → (Maybe a) $ : (∪ (Pair a (Streamof a)) (Suspension a))
procedure
(stream-rest $) → (Streamof a)
$ : (∪ (Pair a (Streamof a)) (Suspension a))
procedure
(stream-take $ n) → (Streamof a)
$ : (Streamof a) n : Natural
1.2.4 Forcing Streams
procedure
(stream-force $) → (∪ Null (Pair a (Streamof a)))
$ : (Streamof a)
procedure
(stream-force-take $ n) → (Listof a)
$ : (Streamof a) n : Natural
procedure
(stream->list $) → (Listof a)
$ : (Streamof a)
> (define $ (stream-lazy (stream 1 2))) > (stream-force $) - : (U (Pairof Positive-Byte (Streamof Positive-Byte)) Null)
'(1 2)
; the pause is the first element > (stream->list (stream-take $ 2)) - : (Listof Positive-Byte)
'(1)
> (stream-force-take $ 1) - : (Listof Positive-Byte)
'(1)
> (stream->list $) - : (Listof Positive-Byte)
'(1 2)
1.2.5 The Stream Monad
1.3 The Core
The core of microKanren.scm: the four goal constructors, and the unification they are built on.
1.3.1 Goal Constructors
procedure
(call/fresh f) → Goal
f : (→ Var Goal)
> (stream->list ((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))
1.3.2 Unification
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.
1.4.1 Goal Forms
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))
1.4.2 Running Goals
1.4.3 Reification
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