A categorical programming language
修訂 | 0f322cea91c2fa1e671ada0a2ab8fda1477c7e44 (tree) |
---|---|
時間 | 2023-01-28 14:30:24 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Search backwards through eval° and cammy°.
I figured it out for eval°, but I do not at all understand why cammy° is
improved by this. Nonetheless, I was able to replace cammy-synth° and
the entire pile of hacks. As a bonus, previous tests which timed out are
now successfully finding valid expressions; djinn is cleverer!
@@ -10,7 +10,7 @@ | ||
10 | 10 | (begin (display (car xs)) (newline) (print-each (cdr xs))))) |
11 | 11 | |
12 | 12 | (define (djinn x s t) |
13 | - (print-each (run x (q) (cammy-synth° q s t)))) | |
13 | + (print-each (run x (q) (cammy° q s t)))) | |
14 | 14 | |
15 | 15 | (match (map (lambda (s) (read (open-input-string s))) |
16 | 16 | (command-line-arguments)) |
@@ -1,4 +1,4 @@ | ||
1 | -(module cammyo (cammy° cammy-prim° cammy-synth° eval°) | |
1 | +(module cammyo (cammy° cammy-prim° eval°) | |
2 | 2 | (import scheme) |
3 | 3 | (import (chicken pretty-print)) |
4 | 4 | (import (mini-kanren)) |
@@ -80,97 +80,13 @@ | ||
80 | 80 | ; Categories |
81 | 81 | ((== expr 'id) (== s t)) |
82 | 82 | ((fresh (f g) (== expr `(comp ,f ,g)) |
83 | - (fresh (y) (cammy° f s y) (cammy° g y t)))) | |
83 | + ; XXX: Why backwards? Should be same rationale as in eval°, but | |
84 | + ; why does it work on types and not just elements? | |
85 | + (fresh (y) (cammy° g y t) (cammy° f s y)))) | |
84 | 86 | )) |
85 | 87 | |
86 | - ; Syntactic composition enforcing normal form. This is just a synthesis helper. | |
87 | - ; Cammy × Cammy <-> Cammy | |
88 | - (define (comp-s° f g fg) (=/= f 'id) (=/= g 'id) (== fg `(comp ,f ,g))) | |
89 | - | |
90 | - ; Cammy expressions which are theorems of BCI combinator calculus. | |
91 | - ; Cammy <-> Ty × Ty × Comb | |
92 | - (define (bci° expr s t comb) | |
93 | - (conde | |
94 | - ((== expr 'id) (== s t) (== comb 'I)) | |
95 | - ((fresh (f g u cf cg) (== expr `(comp ,f ,g)) (== comb `((B ,cg) ,cf)) | |
96 | - (bci° f s u cf) (bci° g u t cg))) | |
97 | - )) | |
98 | - | |
99 | - ; Like cammy°, but suitable for type-directed term synthesis. All expressions | |
100 | - ; are normalized, and logical clauses are ordered to try some expert strategies. | |
101 | - ; Cammy <-> Ty × Ty | |
102 | - (define (cammy-synth° expr s t) | |
103 | - ; s, t, u, v are types | |
104 | - ; f, g are Cammy expressions | |
105 | - (fresh (f g u v) | |
106 | - ; (project (expr s t) (begin (pp `(synth? ,expr : ,s -> ,t)) succeed)) | |
107 | - (conde | |
108 | - ; Try primitives first. | |
109 | - ((cammy-prim° expr s t)) | |
110 | - ; Is it a BCI theorem? | |
111 | - ((fresh (comb) (bci° expr s t comb))) | |
112 | - ; Is it any arrow into 1? | |
113 | - ((== t '1) | |
114 | - ; NB: ignore : X -> 1, but only when X ≠ 1, because otherwise it's | |
115 | - ; the unique arrow, id : 1 -> 1 | |
116 | - (conde | |
117 | - ((== s '1) (== expr 'id)) | |
118 | - ((=/= s '1) (== expr 'ignore)))) | |
119 | - ; Is it an NT? | |
120 | - ((== `(pair ,s ,s) t) (== expr 'dup)) | |
121 | - ((== s `(pair ,t ,u)) (== expr 'fst)) | |
122 | - ((== s `(pair ,u ,t)) (== expr 'snd)) | |
123 | - ((== s `(pair ,u ,v)) (== t `(pair ,v ,u)) (== expr 'swap)) | |
124 | - ((== s `(pair (hom ,u ,t) ,u)) (== expr 'app)) | |
125 | - ((== `(sum ,s ,u) t) (== expr 'left)) | |
126 | - ((== `(sum ,u ,s) t) (== expr 'right)) | |
127 | - ; Is it a tuple lookup? | |
128 | - ((== s `(pair ,u ,v)) | |
129 | - (conde | |
130 | - ((comp-s° 'fst f expr) (cammy-synth° f u t)) | |
131 | - ((comp-s° 'snd f expr) (cammy-synth° f v t)))) | |
132 | - ; Is it a case analysis? | |
133 | - ((== s `(sum ,u ,v)) (cammy-synth° f u t) (cammy-synth° g v t) (== expr `(case ,f ,g))) | |
134 | - ; Is it a tagging or return value? | |
135 | - ((== t `(sum ,u ,v)) | |
136 | - (conde | |
137 | - ((comp-s° f 'left expr) (cammy-synth° f s u)) | |
138 | - ((comp-s° f 'right expr) (cammy-synth° f s v)))) | |
139 | - ; Is it a graph? | |
140 | - ; NB: Want to disallow (pair id id) | |
141 | - ((== `(pair ,s ,u) t) (=/= f 'id) (cammy-synth° f s u) (== expr `(pair id ,f))) | |
142 | - ((== `(pair ,u ,s) t) (=/= f 'id) (cammy-synth° f s u) (== expr `(pair ,f id))) | |
143 | - ; Is it a curry? | |
144 | - ((== t `(hom ,u ,v)) (cammy-synth° f `(pair ,s ,u) v) (== expr `(curry ,f))) | |
145 | - ; Is it an application? | |
146 | - ((cammy-synth° f s `(hom ,u ,t)) (cammy-synth° g s u) (comp-s° `(pair ,f ,g) 'app expr)) | |
147 | - ; Is it a pair-builder? | |
148 | - ((== `(pair ,u ,v) t) (cammy-synth° f s u) (cammy-synth° g s v) (== expr `(pair ,f ,g))) | |
149 | - ; Does it result in a list? | |
150 | - ((== t `(list ,u)) | |
151 | - (conde | |
152 | - ((== s '1) (== expr 'nil)) | |
153 | - ((== s `(pair ,u (list ,u))) (== expr 'cons)))) | |
154 | - ; Is it primitive recursive? | |
155 | - ((== s 'N) (cammy-synth° f '1 t) (=/= g 'id) (cammy-synth° g t t) (== expr `(pr ,f ,g))) | |
156 | - ; Is it a composition? | |
157 | - ; ((comp-s° f g expr) (cammy-synth° f s u) (cammy-synth° g u t)) | |
158 | - ) | |
159 | - ; (project (expr s t) (begin (pp `(found: ,expr : ,s -> ,t)) succeed)) | |
160 | - )) | |
161 | - | |
162 | - (define (not° x y) | |
163 | - (conde | |
164 | - ((== x #t) (== y #f)) | |
165 | - ((== x #f) (== y #t)))) | |
166 | - | |
167 | - (define (conj° x y z) | |
168 | - (conde | |
169 | - ((== x #t) (== y #t) (== z #t)) | |
170 | - ((== x #t) (== y #f) (== z #f)) | |
171 | - ((== x #f) (== y #t) (== z #f)) | |
172 | - ((== x #f) (== y #f) (== z #f)))) | |
173 | - | |
88 | + ; Recursion helper for primitive recursion. | |
89 | + ; Cammy × Cammy × Val <-> Val | |
174 | 90 | (define (pr° x f i o) |
175 | 91 | (conde |
176 | 92 | ((zeroo i) (eval° x 'star o)) |
@@ -181,8 +97,13 @@ | ||
181 | 97 | (define (eval° expr i o) |
182 | 98 | (conde |
183 | 99 | ((== expr 'id) (== i o)) |
184 | - ((fresh (f g u) (== expr `(comp ,f ,g)) | |
185 | - (eval° f i u) (eval° g u o))) | |
100 | + ((fresh (f g) (== expr `(comp ,f ,g)) | |
101 | + ; NB: Search backwards through compositions. | |
102 | + ; Cammy expressions are functional; when inputs are ground, | |
103 | + ; outputs will also be ground, so going backwards doesn't hurt. | |
104 | + ; Contrariwise, some outputs don't correspond to any input, so | |
105 | + ; refutations also need to search backwards. | |
106 | + (fresh (u) (eval° g u o) (eval° f i u)))) | |
186 | 107 | ((== expr 'ignore) (== o 'star)) |
187 | 108 | ((== expr 'fst) (caro i o)) |
188 | 109 | ((== expr 'snd) (cdro i o)) |
@@ -1,6 +1,7 @@ | ||
1 | 1 | ; Extra relations for typical Scheme-flavored miniKanren. |
2 | -(module rels (succ° nth° concat°) | |
2 | +(module rels (concat° succ° nth° not° conj°) | |
3 | 3 | (import scheme) |
4 | + (import (chicken pretty-print)) | |
4 | 5 | (import (mini-kanren)) |
5 | 6 | |
6 | 7 | ; Flatten an arbitrary number of lists into one list by repeated appending. |
@@ -18,7 +19,7 @@ | ||
18 | 19 | |
19 | 20 | ; The successor function. |
20 | 21 | ; Nat <-> Nat |
21 | - (define (succ° n m) (addero 1 '() n m)) | |
22 | + (define (succ° n m) (+o (build-num 1) n m)) | |
22 | 23 | |
23 | 24 | ; The n'th element of a list. |
24 | 25 | ; Nat × X <-> [X] |
@@ -26,4 +27,20 @@ | ||
26 | 27 | (conde |
27 | 28 | ((zeroo n) (caro xs x)) |
28 | 29 | ((fresh (m rest) (succ° m n) (cdro xs rest) (nth° m x rest))))) |
30 | + | |
31 | + ; Boolean NOT. | |
32 | + ; Bool <-> Bool | |
33 | + (define (not° x y) | |
34 | + (conde | |
35 | + ((== x #t) (== y #f)) | |
36 | + ((== x #f) (== y #t)))) | |
37 | + | |
38 | + ; Boolean AND. | |
39 | + ; Bool × Bool <-> Bool | |
40 | + (define (conj° x y z) | |
41 | + (conde | |
42 | + ((== x #t) (== y #t) (== z #t)) | |
43 | + ((== x #t) (== y #f) (== z #f)) | |
44 | + ((== x #f) (== y #t) (== z #f)) | |
45 | + ((== x #f) (== y #f) (== z #f)))) | |
29 | 46 | ) |
@@ -343,16 +343,8 @@ | ||
343 | 343 | be applications of non-core templates |
344 | 344 | * Sunday |
345 | 345 | * Let's do a Pantagruel spec! |
346 | - * But not right now! | |
347 | - * Also Janet apps using JPM don't build on NixOS? | |
348 | - * Let's rewrite Honey with FastAPI! | |
349 | - * And use PyPy! | |
350 | - * But not right now! | |
351 | -* New REPL | |
352 | - * Not sure if there's much need for commands | |
353 | - * Making new dippers, maybe? | |
354 | - * Realized that ":" is not the best command-starter | |
355 | - * Technically ")" would be the best choice since it can't start a legal term | |
346 | + * Janet apps using JPM don't build on NixOS? | |
347 | + * JPM got added to nixpkgs a few months ago, let's try again | |
356 | 348 | * Let's destroy the Python glue |
357 | 349 | * Indeed, let's destroy most of the glue |
358 | 350 | * Use CHICKEN Scheme for the basic REPL |
@@ -361,7 +353,9 @@ | ||
361 | 353 | * Call jelly for optimizing |
362 | 354 | * Call RPython binaries for fast rendering |
363 | 355 | * Need to provide way to dump CAM bytecode; maybe new executable? |
356 | + * Let's just use an envvar | |
364 | 357 | * Maybe Honey was a mistake |
358 | + * And now it's gone | |
365 | 359 | * Slogans? |
366 | 360 | * Cammy is compositional |
367 | 361 | * Cammy is chimeric |