-
Notifications
You must be signed in to change notification settings - Fork 10
/
README
4553 lines (2950 loc) · 123 KB
/
README
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
# The GEB Manual
###### \[in package GEB-DOCS/DOCS\]
Welcome to the GEB project.
## Links
Here is the [official repository](https://github.com/anoma/geb/)
and [HTML documentation](https://anoma.github.io/geb/) for the latest version.
Maintainers: please read the [maintainers guide](https://github.com/anoma/geb/blob/main/docs/maintainers-guide.org)
### code coverage
For test coverage it can be found at the following links:
[SBCL test coverage](./tests/cover-index.html)
[CCL test coverage: current under maintenance](./tests/report.html)
---
Note that due to [#34](https://github.com/anoma/geb/issues/34)
CCL tests are not currently displaying
---
I recommend reading the CCL code coverage version, as it has proper tags.
Currently they are manually generated, and thus for a more accurate assessment see GEB-TEST:CODE-COVERAGE
## Getting Started
Welcome to the GEB Project!
### installation
This project uses [common lisp](https://common-lisp.net/), so a few
dependencies are needed to get around the code-base and start hacking. Namely:
1. [lisp with quicklisp](https://lisp-lang.org/learn/getting-started/).
2. [Emacs](https://en.wikipedia.org/wiki/Emacs) along with one of the following:
- [sly](https://github.com/joaotavora/sly)
- [sly user manual](http://joaotavora.github.io/sly/)
- [slime](https://github.com/slime/slime)
- [slime user manual](http://www.chiark.greenend.org.uk/doc/slime/slime.pdf)
### loading
Now that we have an environment setup, we can load the project, this
can be done in a few steps.
1. Open the `REPL` (sbcl (terminal), `M-x` sly, `M-x` swank)
- For the terminal, this is just calling the [common
lisp](https://common-lisp.net/) implementation from the
terminal.
`user@system:geb-directory % sbcl`.
- For Emacs, this is simply calling either `M-x sly` or `M-x slime`
if you are using either [sly](https://github.com/joaotavora/sly) or [slime](https://github.com/slime/slime)
2. From Emacs: open `geb.asd` and press `C-ck` (`sly-compile-and-load-file`, or
`swank-compile-and-load-file` if you are using swank).
Now that we have the file open, we can now load the system by
writing:
```lisp
;; only necessary for the first time!
(ql:quickload :geb/documentation)
;; if you want to load it in the future
(asdf:load-system :geb/documentation)
;; if you want to load the codbase and run tests at the same time
(asdf:test-system :geb/documentation)
;; if you want to run the tests once the system is loaded!
(geb-test:run-tests)
```
### Geb as a binary
###### \[in package GEB.ENTRY\]
The standard way to use geb currently is by loading the code into
one's lisp environment
```lisp
(ql:quickload :geb)
```
However, one may be interested in running geb in some sort of
compilation process, that is why we also give out a binary for people
to use
An example use of this binary is as follows
```bash
mariari@Gensokyo % ./geb.image -i "foo.lisp" -e "geb.lambda.main::*entry*" -l -p -o "foo.pir"
mariari@Gensokyo % cat foo.pir
def entry x1 = {
(x1)
};%
mariari@Gensokyo % ./geb.image -i "foo.lisp" -e "geb.lambda.main::*entry*" -l -p
def *entry* x {
0
}
mariari@Gensokyo % ./geb.image -h
-i --input string Input geb file location
-e --entry-point string The function to run, should be fully qualified I.E. geb::my-main
-l --stlc boolean Use the simply typed lambda calculus frontend
-o --output string Save the output to a file rather than printing
-v --version boolean Prints the current version of the compiler
-p --vampir string Return a vamp-ir expression
-s --library boolean Print standard library
-h -? --help boolean The current help message
mariari@Gensokyo % ./geb.image -v
0.3.2
```
starting from a file *foo.lisp* that has
any valid lambda form. Good examples can be found at the following section:
GEB.LAMBDA:@STLC
with the term bound to some global variable
```lisp
(in-package :geb.lambda.main)
(defparameter *entry*
(lamb (list (coprod so1 so1))
(index 0)))
```
inside of it.
The command needs an entry-point (-e or --entry-point), as we are
simply call LOAD on the given file, and need to know what to
translate.
from STLC, we expect the form to be wrapped in the
GEB.LAMBDA.SPEC.TYPED which takes both the type and the value to
properly have enough context to evaluate.
It is advised to bind this to a parameter like in our example as -e
expects a symbol.
the -l flag means that we are not expecting a geb term, but rather a
lambda frontend term, this is to simply notify us to compile it as a
lambda term rather than a geb term. In time this will go away
The flag -s prints the standard library the compiler uses. If -p is
used alongside it, the standard library gets printed before the
compiled circuit.
The flag -t after -p signals that the user wants to make an
automatically generated test equality. Given a compiled VampIR
function with name foo and arguments x1...xn prints an equality as
foo x1 ... xn = y
- [function] COMPILE-DOWN &KEY VAMPIR STLC ENTRY LIBRARY TEST (STREAM \*STANDARD-OUTPUT\*)
## Glossary
- [glossary-term] closed type
A closed type is a type that can not be extended dynamically.
A good example of this kind of term is an ML
[ADT](https://en.wikipedia.org/wiki/Algebraic_data_type).
```haskell
data Tree = Empty
| Leaf Int
| Node Tree Tree
```
In our lisp code we have a very similar convention:
```lisp
(in-package :geb.spec)
(deftype substmorph ()
`(or substobj
alias
comp init terminal case pair distribute
inject-left inject-right
project-left project-right))
```
This type is closed, as only one of GEB:SUBSTOBJ, GEB:INJECT-LEFT,
GEB:INJECT-RIGHT etc can form the GEB:SUBSTMORPH type.
The main benefit of this form is that we can be exhaustive over what
can be found in GEB:SUBSTMORPH.
```lisp
(defun so-hom-obj (x z)
(match-of substobj x
(so0 so1)
(so1 z)
(alias (so-hom-obj (obj x) z))
((coprod x y) (prod (so-hom-obj x z)
(so-hom-obj y z)))
((prod x y) (so-hom-obj x (so-hom-obj y z)))))
```
If we forget a case, like GEB:COPROD it wanrs us with an non exhaustion warning.
Meaning that if we update definitions this works well.
---
The main downside is that we can not extend the type after the fact,
meaning that all interfaces on SO-HOM-OBJ must take the unaltered
type. This is in stark contrast to @OPEN-TYPES. To find out more about
the trade offs and usage in the code-base read the section @OPEN-CLOSED.
- [glossary-term] open type
An open type is a type that can be extended by user code down the
line. A good example of this in ML is the [type class
system](https://en.wikipedia.org/wiki/Type_class) found in Haskell.
In our code base, it is simple as creating a @CLOS term
```lisp
(defclass <substobj> (direct-pointwise-mixin) ())
```
and to create a child of it all we need to do is.
```lisp
(defclass so0 (<substobj>) ())
```
Now any methods on GEB:\<SUBSTOBJ> will cover GEB:SO0.
---
The main disadvantage of these is that exhaustion can not be checked,
and thus the user has to know what methods to fill out. In a system
with a bit more checks this is not a problem in practice. To find out
more about the trade offs and usage in the code-base read the section
@OPEN-CLOSED.
- [glossary-term] Common Lisp Object System (CLOS)
The object system found in CL. Has great features like a [Meta Object
Protocol](http://community.schemewiki.org/?meta-object-protocol) that
helps it facilitate extensions.
## Original Efforts
Originally GEB started off as an Idris codebase written by the
designer and creator of GEB, Terence Rokop, However further efforts
spawned for even further formal verification by Artem Gureev. Due
to this, we have plenty of code not in Common Lisp that ought to be
a good read.
### Geb's Idris Code
The Idris folder can be found in the
[geb-idris](https://github.com/anoma/geb/tree/main/geb-idris) folder
provided in the codebase
At the time of this document, there is over 16k lines of Idris code
written. This serves as the bulk of the POC that is GEB and is a
treasure trove of interesting information surrounding category
theory.
### Geb's Agda Code
The Agda folder can be found in the
[geb-agda](https://github.com/anoma/geb/tree/main/geb-agda) folder
provided in the codebase
The Agda codebase serves as a great place to view formally verified
properties about the GEB project. Although @IDRIS is written in a
dependently typed language, it serves as reference example of GEB,
while @AGDA serves as the mathematical formalism proving various
conjectures about GEB
## Categorical Model
Geb is organizing programming language concepts (and entities!) using
[category theory](https://plato.stanford.edu/entries/category-theory/),
originally developed by mathematicians,
but very much alive in programming language theory.
Let us look at a simple well-known example:
the category of sets and functions.
It is the bread and butter example:
sets $A,B,C,…$ play the role of *objects*,
functions are *arrows* between objects $A—f→B$,
and the latter *compose* as functions do,
such that every path of matching functions
$$A—f→B—g→C—h→D$$
composes to a corresponding composite function
$$A—f;g;h→D$$ (or $h∘g∘f$ if you prefer)
and we enjoy the luxury of not having to worry about
the order in which we compose;
for the sake of completeness,
there are identify functions $A —\mathrm{id}\_A→ A$ on each set $A$,
serving as identities
(which correspond to the composite of the empty path on an object).
Sets and functions *together* form **a** category—based on
function composition;
thus, let's call this category *sets-'n'-functions*.
This example,
even “restricted” to *finite sets-'n'-functions*,
will permeate through Geb.
<!--
although the “weird” habit of avoiding
talk about elements of sets as much as possible.
-->
One of the first lessons (in any introduction to category theory)
about *sets-'n'-functions* is the characterization of
[product](https://en.wikipedia.org/wiki/Product_(category_theory)#Product_of_two_objects)s
and [disjoint sum](https://en.wikipedia.org/wiki/Coproduct#Definition)s of sets
in terms of functions alone,
i.e.,
**without *ever* talking about elements of sets**.
Products and co-products are the simplest examples of
*universal constructions*.
One of the first surprises follows suit
when we generalize functions to partial functions,
relations, or even multi-relations:
*we obtain **very** different categories!*
For example,
in the category [*sets-'n'-relations*](https://en.wikipedia.org/wiki/Category_of_relations),
the disjoint union of sets features as both a product and a co-product,
as a categorical construction.
*Do not fear!*
The usual definition of products in terms of elements of sets are
absolutely compatible with the
universal construction in *sets-'n'-functions*.
However we gain the possibility
to compare the “result” of the *universal constructions*
in *sets-'n'-functions* with the one in *sets-'n'-relations*
(as both actually do have products).
for the purposes of Geb,
many things can be expressed in analogy to
the category of *sets-'n'-functions*;
thus a solid understanding of the latter
will be quite useful.
In particular,
we shall rely on the following
universal constructions:
1. The construction of binary products $A × B$ of sets $A,B$, and the empty product $mathsf{1}$.
2. The construction of “function spaces” $B^A$ of sets $A,B$, called *exponentials*,
i.e., collections of functions between pairs of sets.
3. The so-called [*currying*](https://en.wikipedia.org/wiki/Currying)
of functions,
$C^{(B^A)} cong C^{(A × B)}$,
such that providing several arguments to a function can done
either simultaneously, or in sequence.
4. The construction of sums (a.k.a. co-products) $A + B$ of sets $A,B$,
corresponding to forming disjoint unions of sets;
the empty sum is $varnothing$.
Product, sums and exponentials
are the (almost) complete tool chest for writing
polynomial expressions, e.g.,
$$Ax^{sf 2} +x^{sf 1} - Dx^{sf 0}.$$
(We need these later to define [“algebraic data types”](https://en.wikipedia.org/wiki/Polynomial_functor_(type_theory)).)
In the above expression,
we have sets instead of numbers/constants
where $ mathsf{2} = lbrace 1, 2 rbrace$,
$ mathsf{1} = lbrace 1 rbrace$,
$ mathsf{0} = lbrace rbrace = varnothing$,
and $A$ and $B$ are arbitrary (finite) sets.
We are only missing a counterpart for the *variable*!
Raising an arbitrary set to “the power” of a constant set
happens to have a very natural counterpart:
the central actor of
[the most-well known fundamental result about categories](https://en.wikipedia.org/wiki/Yoneda_lemma),
which generalizes Cayley's Theorem, i.e., the [Yoneda embedding](https://en.wikipedia.org/wiki/Yoneda_lemma#The_Yoneda_embedding).
If you are familiar with the latter,
buckle up and jump to @POLY-SETS.
Have a look at our streamlined account of @YONEDA-LEMMA
if you are familiar with Cartesian closed categories,
or take it slow and read up on the background in
one of the classic or popular
[textbooks](https://www.goodreads.com/shelf/show/category-theory).
Tastes tend to vary.
However,
Benjamin Pierce's
[*Basic Category Theory for Computer Scientists*](https://mitpress.mit.edu/9780262660716/) deserves being pointed out
as it is very amenable *and*
covers the background we need in 60 short pages.
### Morphisms
### Objects
### The Yoneda Lemma
### Poly in Sets
## Project Idioms and Conventions
The Geb Project is written in [Common
Lisp](https://common-lisp.net/), which means the authors have a great
choice in freedom in how the project is laid out and operates. In
particular the style of [Common Lisp](https://common-lisp.net/) here
is a
[functional](https://en.wikipedia.org/wiki/Functional_programming)
style with some
[OO](https://en.wikipedia.org/wiki/Object-oriented_programming) idioms
in the style of [Smalltalk](https://en.wikipedia.org/wiki/Smalltalk).
The subsections will outline many idioms that can be found throughout
the codebase.
### Spec Files, Main Files and Project Layout
###### \[in package GEB.SPECS\]
The codebase is split between many files. Each folder can be seen as
a different idea within geb itself! Thus the `poly` has packages
revolving around polynomials, the `geb` folder has packages regarding
the main types of geb GEB.SPEC:@GEB-SUBSTMU and
GEB.SPEC:@GEB-SUBSTMORPH, etc etc.
The general layout quirk of the codebase is that packages like
`geb.package.spec` defines the specification for the base types for
any category we wish to model, and these reside in the `specs` folder
not in the folder that talks about the packages of those types. This
is due to loading order issues, we thus load the `specs` packages
before each of their surrounding packages, so that each package can
built off the last. Further, packages like `geb.package.main` define
out most of the functionality of the package to be used by other
packages in `geb.package`, then all of these are reexported out in the
`geb.package` package
Further to make working with each package of an idea is easy, we have
the main package of the folder (typically named the same as the folder
name) reexport most important components so if one wants to work with
the fully fledged versions of the package they can simply without
having to import too many packages at once.
For example, the `geb.poly.spec` defines out the types and data
structures of the GEB.POLY.SPEC:@POLY, this is then rexported
in `geb.poly`, giving the module `geb.poly` a convenient interface for
all functions that operate on `geb.poly`.
### Open Types versus Closed Types
@CLOSED-TYPE's and @OPEN-TYPE's both have their perspective
tradeoff of openness versus exhaustiveness (see the linked articles
for more on that). Due to this, they both have their own favorable
applications. I would argue that a closed
[ADT](https://en.wikipedia.org/wiki/Algebraic_data_type) type is great
tool for looking at a function mathematically and treating the object
as a whole rather than piecemeal. Whereas a more open extension is
great for thinking about how a particular object/case behaves. They
are different mindsets for different styles of code.
In the geb project, we have chosen to accept both styles, and allow
both to coexist in the same setting. We have done this with a two part
idiom.
```lisp
(deftype substobj ()
`(or alias prod coprod so0 so1))
(defclass <substobj> (direct-pointwise-mixin) ())
(defclass so0 (<substobj>) ...)
(defclass prod (<substobj>) ...)
```
The @CLOSED-TYPE is GEB:SUBSTOBJ, filling and defining every structure
it knows about. This is a fixed idea that a programmer may statically
update and get exhaustive warnings about. Whereas GEB:\<SUBSTOBJ> is
the open interface for the type. Thus we can view \[GEB:\<SUBSTOBJ>\] as
the general idea of a \[GEB:SUBSTOBJ\]. Before delving into how we combine
these methods, let us look at two other benefits given by \[GEB:\<SUBSTOBJ>\]
1. We can put all the @MIXINS into the superclass to enforce that any
type that extends it has the extended behaviors we wish. This is a
great way to generically enhance the capabilities of the type
without operating on it directly.
2. We can dispatch on GEB:\<SUBSTOBJ> since DEFMETHOD only works on
@CLOS types and not generic types in CL.
#### Methods for closed and open types
With these pieces in play let us explore how we write a method in a
way that is conducive to open and closed code.
```lisp
(in-package :geb)
(defgeneric to-poly (morphism))
(defmethod to-poly ((obj <substmorph>))
(typecase-of substmorph obj
(alias ...)
(substobj (error "Impossible")
(init 0)
(terminal 0)
(inject-left poly:ident)
(inject-right ...)
(comp ...)
(case ...)
(pair ...)
(project-right ...)
(project-left ...)
(distribute ...)
(otherwise (subclass-responsibility obj))))
(defmethod to-poly ((obj <substobj>))
(declare (ignore obj))
poly:ident)
```
In this piece of code we can notice a few things:
1. We case on \[GEB:SUBSTMORPH\] exhaustively
2. We cannot hit the \[GEB:\<SUBSTOBJ>\] case due to method dispatch
3. We have this \[GEB.UTILS:SUBCLASS-RESPONSIBILITY\] function getting called.
4. We can write further methods extending the function to other subtypes.
Thus the \[GEB.COMMON:TO-POLY\] function is written in such a way that it
supports a closed definition and open extensions, with
\[GEB.UTILS:SUBCLASS-RESPONSIBILITY\] serving to be called if an
extension a user wrote has no handling of this method.
Code can also be naturally written in a more open way as well, by
simply running methods on each class instead.
#### Potential Drawback and Fixes
One nasty drawback is that we can't guarantee the method exists. In
java this can easily be done with interfaces and then enforcing they
are fulfilled. Sadly CL has no such equivalent. However, this is all
easily implementable. If this ever becomes a major problem, it is
trivial to implement this by registering the subclasses, and the
perspective methods, and scouring the image for instance methods, and
computing if any parent class that isn't the one calling
responsibility fulfills it. Thus, in practice, you should be able to
ask the system if any particular extension fulfills what extension
sets that the base object has and give CI errors if they are not
fulfilled, thus enforcing closed behavior when warranted.
### ≺Types≻
These refer to the @OPEN-TYPE variant to a @CLOSED-TYPE. Thus when
one sees a type like GEB:<SUBSTOBJ> it is the open version of
GEB:SUBSTOBJ. Read @OPEN-CLOSED for information on how to use them.
## The Geb Model
###### \[in package GEB\]
Everything here relates directly to the underlying machinery of
GEB, or to abstractions that help extend it.
### The Categorical Interface
###### \[in package GEB.MIXINS\]
This covers the main Categorical interface required to be used and
contained in various data structures
- [class] CAT-OBJ
I offer the service of being a base category objects with no
extensions
- [class] CAT-MORPH
I offer the service of being a base categorical morphism with no
extensions
- [generic-function] DOM X
Grabs the domain of the morphism. Returns a CAT-OBJ
- [generic-function] CODOM X
Grabs the codomain of the morphism. Returns a CAT-OBJ
- [generic-function] CURRY-PROD CAT-MORPH CAT-LEFT CAT-RIGHT
Curries the given product type given the
product. This returns a CAT-MORPH.
This interface version takes the left and right product type to
properly dispatch on. Instances should specialize on the CAT-RIGHT argument
Use GEB.MAIN:CURRY instead.
### Geneircs
###### \[in package GEB.GENERICS\]
These functions represent the generic functions that can be run on
many parts of the compiler, they are typically rexported on any
package that implements the given generic function.
You can view their documentation in their respective API sections.
The main documentation for the functionality is given here, with
examples often given in the specific methods
- [generic-function] GAPPLY MORPHISM OBJECT
Applies a given Moprhism to a given object.
This is practically a naive interpreter for any category found
throughout the codebase.
Some example usages of GAPPLY are.
```lisp
GEB> (gapply (comp
(mcase geb-bool:true
geb-bool:not)
(->right so1 geb-bool:bool))
(left so1))
(right s-1)
GEB> (gapply (comp
(mcase geb-bool:true
geb-bool:not)
(->right so1 geb-bool:bool))
(right so1))
(left s-1)
```
- [generic-function] WELL-DEFP-CAT MORPHISM
Given a moprhism of a category, checks that
it is well-defined. E.g. that composition of morphism is
well-defined by checking that the domain of MCAR corresponds
to the codomain of MCADR
- [generic-function] MAYBE OBJECT
Wraps the given OBJECT into a Maybe monad The Maybe monad in this
case is simply wrapping the term in a coprod
of so1
- [generic-function] SO-HOM-OBJ OBJECT1 OBJECT2
Takes in X and Y Geb objects and provides an internal hom-object
(so-hom-obj X Y) representing a set of functions from X to Y
- [generic-function] SO-EVAL OBJECT1 OBJECT2
Takes in X and Y Geb objects and provides an evaluation morphism
(prod (so-hom-obj X Y) X) -> Y
- [generic-function] WIDTH OBJECT
Given an OBJECT of Geb presents it as a SeqN object. That is,
width corresponds the object part of the to-seqn functor.
- [generic-function] TO-CIRCUIT MORPHISM NAME
Turns a MORPHISM into a Vampir circuit. the NAME is the given name of
the output circuit.
- [generic-function] TO-BITC MORPHISM
Turns a given MORPHISM into a \[GEB.BITC.SPEC:BITC\]
- [generic-function] TO-SEQN MORPHISM
Turns a given MORPHISM into a \[GEB.SEQN.SPEC:SEQN\]
- [generic-function] TO-POLY MORPHISM
Turns a given MORPHISM into a \[GEB.POLY.SPEC:POLY\]
- [generic-function] TO-CAT CONTEXT TERM
Turns a MORPHISM with a context into Geb's Core category
- [generic-function] TO-VAMPIR MORPHISM VALUES CONSTRAINTS
Turns a MORPHISM into a Vampir circuit, with concrete values.
The more natural interface is \[TO-CIRCUIT\], however this is a more low
level interface into what the polynomial categories actually
implement, and thus can be extended or changed.
The VALUES are likely vampir values in a list.
The CONSTRAINTS represent constraints that get creating
### Core Category
###### \[in package GEB.SPEC\]
The underlying category of GEB. With @GEB-SUBSTMU covering the
shapes and forms (GEB-DOCS/DOCS:@OBJECTS) of data while @GEB-SUBSTMORPH
deals with concrete GEB-DOCS/DOCS:@MORPHISMS within the category.
From this category, most abstractions will be made, with
SUBSTOBJ serving as a concrete type layout, with
SUBSTMORPH serving as the morphisms between different
SUBSTOBJ types. This category is equivalent to
[finset](https://ncatlab.org/nlab/show/FinSet).
A good example of this category at work can be found within the
GEB-BOOL::@GEB-BOOL section.
#### Subst Obj
This section covers the objects of the SUBSTMORPH
category. Note that SUBSTOBJ refers to the
\[GEB-DOCS/DOCS:@CLOSED-TYPE\], whereas \<SUBSTOBJ> refers
to the \[GEB-DOCS/DOCS:@OPEN-TYPE\] that allows for user extension.
- [type] SUBSTOBJ
- [class] <SUBSTOBJ> \<SUBSTMORPH> DIRECT-POINTWISE-MIXIN META-MIXIN CAT-OBJ
the class corresponding to SUBSTOBJ. See GEB-DOCS/DOCS:@OPEN-CLOSED
SUBSTOBJ type is not a constructor itself, instead it's
best viewed as the sum type, with the types below forming the
constructors for the term. In ML we would write it similarly to:
```haskell
type substobj = so0
| so1
| prod
| coprod
```
- [class] PROD \<SUBSTOBJ>
The PRODUCT object. Takes two CAT-OBJ values that
get put into a pair.
The formal grammar of PRODUCT is
```lisp
(prod mcar mcadr)
```
where PROD is the constructor, \[MCAR\] is the left value of the
product, and \[MCADR\] is the right value of the product.
Example:
```lisp
(geb-gui::visualize (prod geb-bool:bool geb-bool:bool))
```
Here we create a product of two \[GEB-BOOL:BOOL\] types.
- [class] COPROD \<SUBSTOBJ>
the CO-PRODUCT object. Takes CAT-OBJ values that
get put into a choice of either value.
The formal grammar of PRODUCT is
```lisp
(coprod mcar mcadr)
```
Where CORPOD is the constructor, \[MCAR\] is the left choice of
the sum, and \[MCADR\] is the right choice of the sum.
Example:
```lisp
(geb-gui::visualize (coprod so1 so1))
```
Here we create the boolean type, having a choice between two unit
values.
- [class] SO0 \<SUBSTOBJ>
The Initial Object. This is sometimes known as the
[VOID](https://en.wikipedia.org/wiki/Void_type) type.
the formal grammar of SO0 is
```lisp
so0
```
where SO0 is `THE` initial object.
Example
`lisp
`
- [class] SO1 \<SUBSTOBJ>
The Terminal Object. This is sometimes referred to as the
[Unit](https://en.wikipedia.org/wiki/Unit_type) type.
the formal grammar or SO1 is
```lisp
so1
```
where SO1 is `THE` terminal object
Example
```lisp
(coprod so1 so1)
```
Here we construct \[GEB-BOOL:BOOL\] by simply stating that we have the
terminal object on either side, giving us two possible ways to fill
the type.
```lisp
(->left so1 so1)
(->right so1 so1)
```
where applying \[->LEFT\] gives us the left unit, while \[->RIGHT\] gives
us the right unit.
The @GEB-ACCESSORS specific to @GEB-SUBSTMU
- [accessor] MCAR PROD (:MCAR)
- [accessor] MCADR PROD (:MCADR)
- [accessor] MCAR COPROD (:MCAR)
- [accessor] MCADR COPROD (:MCADR)
#### Subst Morph
The overarching types that categorizes the SUBSTMORPH
category. Note that SUBSTMORPH refers to the
\[GEB-DOCS/DOCS:@CLOSED-TYPE\], whereas \<SUBSTMORPH> refers
to the \[GEB-DOCS/DOCS:@OPEN-TYPE\] that allows for user extension.
- [type] SUBSTMORPH
The morphisms of the SUBSTMORPH category
- [class] <SUBSTMORPH> DIRECT-POINTWISE-MIXIN META-MIXIN CAT-MORPH
the class type corresponding to SUBSTMORPH. See GEB-DOCS/DOCS:@OPEN-CLOSED
SUBSTMORPH type is not a constructor itself, instead it's
best viewed as the sum type, with the types below forming the
constructors for the term. In ML we would write it similarly to:
```haskell
type substmorph = comp
| substobj
| case
| init
| terminal
| pair
| distribute
| inject-left
| inject-right
| project-left
| project-right
```
Note that an instance of SUBSTOBJ, acts like the identity
morphism to the layout specified by the given SUBSTOBJ. Thus
we can view this as automatically lifting a SUBSTOBJ into a
SUBSTMORPH
- [class] COMP \<SUBSTMORPH>
The composition morphism. Takes two CAT-MORPH values that get
applied in standard composition order.
The formal grammar of COMP is
```lisp
(comp mcar mcadr)
```
which may be more familiar as
```haskell
g 。f
```
Where COMP( 。) is the constructor, \[MCAR\](g) is the second morphism
that gets applied, and \[MCADR\](f) is the first morphism that gets
applied.
Example:
```lisp
(geb-gui::visualize
(comp
(<-right so1 geb-bool:bool)
(pair (<-left so1 geb-bool:bool)
(<-right so1 geb-bool:bool))))
```
In this example we are composing two morphisms. the first morphism
that gets applied (\[PAIR\] ...) is the identity function on the
type (PROD SO1 \[GEB-BOOL:BOOL\]), where we pair the
[left projection](PROJECT-LEFT) and the [right
projection](PROJECT-RIGHT), followed by taking the [right
projection](PROJECT-RIGHT) of the type.
Since we know (COMP f id) is just f per the laws of category
theory, this expression just reduces to
```lisp
(<-right so1 geb-bool:bool)
```
- [class] CASE \<SUBSTMORPH>
Eliminates coproducts. Namely Takes two CAT-MORPH values, one
gets applied on the left coproduct while the other gets applied on the
right coproduct. The result of each CAT-MORPH values must be
the same.
The formal grammar of CASE is:
```lisp
(mcase mcar mcadr)
```
Where \[MCASE\] is the constructor, \[MCAR\] is the morphism that gets
applied to the left coproduct, and \[MCADR\] is the morphism that gets
applied to the right coproduct.
Example:
```lisp
(comp
(mcase geb-bool:true
geb-bool:not)
(->right so1 geb-bool:bool))
```
In the second example, we inject a term with the shape \[GEB-BOOL:BOOL\]
into a pair with the shape (SO1 × \[GEB-BOOL:BOOL\]), then we use
\[MCASE\] to denote a morphism saying. IF the input is of the shape \[SO1\],
then give us True, otherwise flip the value of the boolean coming in.
- [class] INIT \<SUBSTMORPH>
The INITIAL Morphism, takes any \[CAT-OBJ\] and
creates a moprhism from SO0 (also known as void) to the object given.
The formal grammar of INITIAL is