A categorical programming language
修订版 | 9cc1c3a0fccc5664e0d4e3413783588c23aed667 (tree) |
---|---|
时间 | 2022-04-01 13:37:56 |
作者 | Corbin <cds@corb...> |
Commiter | Corbin |
Get faster fractal membership working, somewhat.
I'm not quite confident in the correctness of my step "monad", which
deliberately breaks the monad laws to facilitate counting evaluation
steps. I'm also not sure why it's so slow.
@@ -1,6 +1,7 @@ | ||
1 | 1 | import math, sys |
2 | 2 | |
3 | -from rpython.rlib.jit import JitDriver, set_param, unroll_safe | |
3 | +from rpython.rlib.jit import JitDriver, unroll_safe #, set_param | |
4 | +from rpython.rlib.rfile import create_stdio | |
4 | 5 | from rpython.rlib.rfloat import string_to_float |
5 | 6 | from rpython.rlib.rstring import StringBuilder, split |
6 | 7 |
@@ -77,6 +78,7 @@ def multisample(program, radius, x, y): | ||
77 | 78 | return finishChannel(r / l), finishChannel(g / l), finishChannel(b / l) |
78 | 79 | |
79 | 80 | def drawPixels(size, program, window): |
81 | + _, stdout, _ = create_stdio() | |
80 | 82 | sb = StringBuilder() |
81 | 83 | i = 0 |
82 | 84 | while i < size: |
@@ -84,6 +86,9 @@ def drawPixels(size, program, window): | ||
84 | 86 | r, g, b = multisample(program, window.pixelRadius, c1, c2) |
85 | 87 | sb.append(chr(r) + chr(g) + chr(b)) |
86 | 88 | i += 1 |
89 | + if not (i % 1000): | |
90 | + stdout.write(".") | |
91 | + stdout.flush() | |
87 | 92 | return sb.build() |
88 | 93 | |
89 | 94 | def drawPNG(program, filename, corners, width, height): |
@@ -95,7 +100,7 @@ def drawPNG(program, filename, corners, width, height): | ||
95 | 100 | |
96 | 101 | |
97 | 102 | def main(argv): |
98 | - set_param(None, "trace_limit", 50001) | |
103 | + # set_param(None, "trace_limit", 50001) | |
99 | 104 | |
100 | 105 | prog = argv[1] |
101 | 106 | window = [string_to_float(s) for s in split(argv[2])] |
@@ -69,19 +69,16 @@ def repl(hive, stdin, stdout): | ||
69 | 69 | command(hive, line[1], line[3:]) |
70 | 70 | continue |
71 | 71 | sexp, trail = parse(line) |
72 | - print "Got:", line | |
73 | - print "S-expression:", sexp.asStr() | |
74 | - print "Trail:", trail | |
75 | 72 | try: |
76 | 73 | sexp = sexp.canonicalize(hive) |
77 | - print "Canonicalized:", sexp.asStr() | |
74 | + # print "Canonicalized:", sexp.asStr() | |
78 | 75 | except MissingAtom as ma: |
79 | 76 | print "Couldn't canonicalize S-expression; missing atom:", ma.atom |
80 | 77 | sexp = jellify(sexp) |
81 | - print "Jellified:", sexp.asStr() | |
78 | + # print "Jellified:", sexp.asStr() | |
82 | 79 | try: |
83 | 80 | arrow = sexp.buildArrow() |
84 | - print "Arrow:", arrow | |
81 | + # print "Arrow:", arrow | |
85 | 82 | cs = ConstraintStore() |
86 | 83 | domain, codomain = arrow.types(cs) |
87 | 84 | extractor = TypeExtractor(cs, PlaintextTypeFormatter()) |
@@ -0,0 +1,2 @@ | ||
1 | +The type $[2]$ can be interpreted as a type of natural numbers equipped with a | |
2 | +relatively fast primitive recursion. |
@@ -0,0 +1,9 @@ | ||
1 | +(comp | |
2 | + (fold (pair t nil) | |
3 | + (comp | |
4 | + (comp pair/assl | |
5 | + (pair/mapfst (comp bool/half-adder pair/swap))) | |
6 | + (comp pair/assr (pair/mapsnd cons)))) | |
7 | + (uncurry (bool/if (list/conspair (fun/const t) id) id))) | |
8 | + | |
9 | +The successor of a natural number is also a natural number. |
@@ -0,0 +1 @@ | ||
1 | +nil |
@@ -0,0 +1,3 @@ | ||
1 | +(pair bool/xor conj) | |
2 | + | |
3 | +Add two bits, returning a pair of the result and carry bit. |
@@ -0,0 +1,3 @@ | ||
1 | +(fold f bool/xor) | |
2 | + | |
3 | +The parity of a list of bits. |
@@ -0,0 +1,3 @@ | ||
1 | +(fold zero (uncurry (bool/if succ id))) | |
2 | + | |
3 | +The number of set bits in a list of bits. |
@@ -0,0 +1,3 @@ | ||
1 | +(comp (pair disj (comp conj not)) conj) | |
2 | + | |
3 | +The exclusive-or operation, also known as the parity operation. |
@@ -0,0 +1,5 @@ | ||
1 | +(comp (fractal-membership-fast v2/burning-ship nat/256) (v3/broadcast (f/subpair (fun/const f-one) id))) | |
2 | + | |
3 | +Draw membership for the [Burning Ship | |
4 | +fractal](https://en.wikipedia.org/wiki/Burning_Ship_fractal), a relative of | |
5 | +the Mandelbrot set. |
@@ -1,6 +1,4 @@ | ||
1 | -(comp | |
2 | - (fractal-membership v2/burning-ship nat/256) | |
3 | - (v3/broadcast (f/subpair (fun/const f-one) id))) | |
1 | +(comp (fractal-membership v2/burning-ship nat/256) (v3/broadcast (f/subpair (fun/const f-one) id))) | |
4 | 2 | |
5 | 3 | Draw membership for the [Burning Ship |
6 | 4 | fractal](https://en.wikipedia.org/wiki/Burning_Ship_fractal), a relative of |
@@ -1,6 +1,4 @@ | ||
1 | -(comp | |
2 | - (fractal-membership v2/mandelbrot nat/256) | |
3 | - (v3/broadcast (f/subpair (fun/const f-one) id))) | |
1 | +(comp (fractal-membership v2/mandelbrot nat/256) (v3/broadcast (f/subpair (fun/const f-one) id))) | |
4 | 2 | |
5 | 3 | Draw membership in the [Mandelbrot |
6 | 4 | set](https://en.wikipedia.org/wiki/Mandelbrot_set). |
@@ -0,0 +1,3 @@ | ||
1 | +The function type $\mathbb{N}^\mathbb{N}$ can be interpreted as a [formal | |
2 | +power series](https://en.wikipedia.org/wiki/Formal_power_series) on the | |
3 | +natural numbers with coefficients in the natural numbers. |
@@ -0,0 +1,3 @@ | ||
1 | +(curry (comp (comp (pair/mapsnd pair/dup) (v2/map2 fun/app)) nat/add)) | |
2 | + | |
3 | +The sum of two formal power series. |
@@ -0,0 +1,3 @@ | ||
1 | +(curry (comp (comp (pair/mapsnd succ) (pair fun/app snd)) nat/mul)) | |
2 | + | |
3 | +The formal derivative of a formal power series. |
@@ -0,0 +1,3 @@ | ||
1 | +(comp pair/swap fun/app) | |
2 | + | |
3 | +Extract a coefficient from a formal power series. |
@@ -0,0 +1,3 @@ | ||
1 | +(curry (comp fst zero)) | |
2 | + | |
3 | +The zero formal power series. |
@@ -0,0 +1,3 @@ | ||
1 | +(comp (comp @0 (pair v2/complex/mag-2 (pair left (comp ignore right)))) bool/pick) | |
2 | + | |
3 | +Take a step in an IFS, failing if the step has magnitude 2 or greater. |
@@ -0,0 +1,5 @@ | ||
1 | +(comp (iter-fractal-fast @0 @1) (case (fun/const f-one) (fun/const f-zero))) | |
2 | + | |
3 | +Iterate a fractal for a maximum number of steps, and return a value in $[0,1]$ | |
4 | +indicating how many steps were taken, with 1 indicating that the fractal did | |
5 | +not diverge. |
@@ -1,3 +0,0 @@ | ||
1 | -(curry (fun/apppair fst (comp snd @0))) | |
2 | - | |
3 | -The inverse-image functor for an arbitrary classifier. |
@@ -0,0 +1,4 @@ | ||
1 | +(curry (comp fun/app @0)) | |
2 | + | |
3 | +Postcompose a function type with an arrow. This is like one version of the | |
4 | +Yoneda embedding for the given arrow. |
@@ -0,0 +1,5 @@ | ||
1 | +(curry (fun/apppair fst (comp snd @0))) | |
2 | + | |
3 | +Precompose a function type with an arrow. This is like the inverse-image | |
4 | +functor for an arbitrary classifier. It is also like one version of the Yoneda | |
5 | +embedding for the given arrow. |
@@ -0,0 +1,5 @@ | ||
1 | +(fun/unname (comp @1 | |
2 | + (step-iter (fractal-maybe | |
3 | + (fun/unname (comp (comp f-zero pair/dup) @0)))))) | |
4 | + | |
5 | +Given a maximum number of steps, iterate the given fractal. |
@@ -0,0 +1,13 @@ | ||
1 | +(pr @0 @1) | |
2 | + | |
3 | +@0: 1 -> [X, X + N] | |
4 | +@1: [X, X + N] -> [X, X + N] | |
5 | +(uncurry @1) : [X, X + N] x X -> X + N | |
6 | + | |
7 | +Given X -> X + 1 | |
8 | +N -> [X, X + N] | |
9 | +max iterations -> [x, | |
10 | + x after max iterations + number of iterations before failing] | |
11 | + | |
12 | +Intermediate state is more like: | |
13 | +X x N -> X x N + N |
@@ -0,0 +1,3 @@ | ||
1 | +(comp list/uncons (case snd nil)) | |
2 | + | |
3 | +The tail of a list. The tail of the empty list is the empty list. |
@@ -0,0 +1,2 @@ | ||
1 | +The function type $X^{X \times X}$ can be interpreted as the type of magmas on | |
2 | +$X$. A magma is a binary operation. |
@@ -0,0 +1,3 @@ | ||
1 | +(fun/precomp pair/swap) | |
2 | + | |
3 | +Braid a magma, obtaining its opposite magma. |
@@ -0,0 +1,3 @@ | ||
1 | +(fun/precomp pair/dup) | |
2 | + | |
3 | +A magma can be squared to produce an endomorphism. |
@@ -0,0 +1 @@ | ||
1 | +(comp @0 (case (comp (pair id (fun/const (comp zero succ))) left) (comp zero right))) |
@@ -0,0 +1,3 @@ | ||
1 | +(curry (comp (pair (fun/apppair (comp fst snd) snd) (comp fst fst)) @0)) | |
2 | + | |
3 | +Internal composition in any monad, built from the internal bind. |
@@ -0,0 +1,12 @@ | ||
1 | +(pr | |
2 | + (fun/name @0) | |
3 | + (comp (pair id (fun/const (fun/name @2))) (monads/int-comp @1))) | |
4 | + | |
5 | +Given a unit and internal bind in some monad, iterate an endomorphism in that | |
6 | +monad. | |
7 | + | |
8 | +For example, to iterate in the maybe monad: | |
9 | + | |
10 | + (monads/iter monads/maybe/unit monads/maybe/int-bind @0) | |
11 | + | |
12 | +Iteration can terminate early in short-circuiting monads. |
@@ -0,0 +1,3 @@ | ||
1 | +(comp fun/distribl (case (comp pair/swap fun/app) (comp ignore right))) | |
2 | + | |
3 | +An internal version of bind for the maybe monad. |
@@ -0,0 +1,2 @@ | ||
1 | +For a given type $X$, the function type $X^X$ of | |
2 | +[endomorphisms](https://ncatlab.org/nlab/show/endomorphism) forms a monoid. |
@@ -0,0 +1,3 @@ | ||
1 | +fun/int-comp | |
2 | + | |
3 | +Addition in an endomorphism monoid. |
@@ -0,0 +1,3 @@ | ||
1 | +(fun/name id) | |
2 | + | |
3 | +The zero of an endomorphism monoid. |
@@ -1 +1 @@ | ||
1 | -(comp (pair nat/2 nat/8) nat/exp) | |
1 | +(comp (pair nat/8 nat/2) nat/exp) |
@@ -1 +1 @@ | ||
1 | -(comp (pair nat/2 nat/3) nat/exp) | |
1 | +(comp (pair nat/3 nat/2) nat/exp) |
@@ -0,0 +1,3 @@ | ||
1 | +(comp (pair nat/2 nat/9) nat/exp) | |
2 | + | |
3 | + |
@@ -0,0 +1 @@ | ||
1 | +(comp (pair nat/2 nat/3) nat/exp) |
@@ -0,0 +1,11 @@ | ||
1 | +(comp fun/distribl | |
2 | + (case | |
3 | + (comp | |
4 | + (pair (fun/apppair snd (comp fst fst)) (comp fst snd)) | |
5 | + (comp fun/distribl | |
6 | + (case | |
7 | + (comp (comp pair/assr (pair/mapsnd nat/add)) left) | |
8 | + (comp nat/add right)))) | |
9 | + (comp fst right))) | |
10 | + | |
11 | +(X x N + N) x [X, Y x N + N] -> Y x N + N |
@@ -0,0 +1,10 @@ | ||
1 | +(curry | |
2 | + (comp | |
3 | + (comp | |
4 | + (pair (comp fst fst) (fun/apppair (comp fst snd) snd)) | |
5 | + fun/distribr) | |
6 | + (case fun/app (comp snd right)))) | |
7 | + | |
8 | +([Y x N, Z x N + N] x [X x N, Y x N + N]) x (X x N) -> Z x N + N | |
9 | + | |
10 | +[Y x N, Z x N + N] x [X x N, Y x N + N] -> [X x N, Z x N + N] |
@@ -0,0 +1,3 @@ | ||
1 | +(monads/iter step-unit step-bind (maybe-step @0)) | |
2 | + | |
3 | + |
@@ -0,0 +1,3 @@ | ||
1 | +(comp (pair id (fun/const zero)) left) | |
2 | + | |
3 | +The unit of a sort of step monad. |
@@ -0,0 +1,3 @@ | ||
1 | +(comp (comp (pair/tensor @0 succ) fun/distribl) (case left (comp snd right))) | |
2 | + | |
3 | +Take a step along a partial arrow, incrementing the number of steps taken. |
@@ -1,3 +1,3 @@ | ||
1 | -(curry (comp fun/app @0)) | |
1 | +(fun/postcomp @0) | |
2 | 2 | |
3 | 3 | The Yoneda embedding of an arrow. |
@@ -16,6 +16,8 @@ in pkgs.stdenv.mkDerivation { | ||
16 | 16 | pythonPackages.pyflakes |
17 | 17 | # using cammy-comb |
18 | 18 | graphviz |
19 | + # using cammy-draw | |
20 | + pv | |
19 | 21 | # using cammy-weave |
20 | 22 | pandoc texlive.combined.scheme-small |
21 | 23 | # using cammy-repl |
@@ -6,7 +6,6 @@ | ||
6 | 6 | * More list manipulations |
7 | 7 | * list/eq : [X × X, 2] → [[X] × [X], 2] |
8 | 8 | * list/zip : [X] × [Y] → [X × Y] |
9 | - * list/tail : [X] → [X] | |
10 | 9 | * rat |
11 | 10 | * Using binary quote notation? |
12 | 11 | * Continued fractions? |
@@ -19,12 +18,11 @@ | ||
19 | 18 | * Euler's constant e |
20 | 19 | * Euler's constant gamma |
21 | 20 | * Double-negation monad for CPS? |
22 | - * Cont is available but not fully developed | |
23 | - * monads/cont/join, monads/cont/bind, etc. | |
24 | 21 | * fun/name should always start from 1 |
25 | 22 | * Requires changing some callers |
26 | 23 | * Might not be feasible unless we switch to stricter monoidal categories |
27 | 24 | * We'd need an equivalence X × 1 → X |
25 | + * swap and dup would need to be primitive again too | |
28 | 26 | * Prove that nat/add is smallest with its behavior |
29 | 27 | * Streams |
30 | 28 | * Monad: X → [N, X] |
@@ -44,14 +42,6 @@ | ||
44 | 42 | * hook the hive to load a specialized routine during codeload? |
45 | 43 | * pair/swap is builtin to movelist and jelly |
46 | 44 | * this might be fundamental to symmetric monoidal categories or CCCs |
47 | -* Search for more optimizations | |
48 | - * Some arrows have inferred types that suggest they should be simplifiable | |
49 | - * X -> X: should be id? | |
50 | - * X -> 1: should be ignore | |
51 | - * 1 -> 2: should be t or f | |
52 | -* Refactoring tools | |
53 | - * Find all leaves in a hive | |
54 | - * Rename an expression and change all callers | |
55 | 45 | * Maybe allow inductive datatype definitions during toolchain build time |
56 | 46 | * Start by factoring out N and lists into inductive datatype modules somehow |
57 | 47 | * Then add trees, etc. |