Coder Social home page Coder Social logo

catt's Introduction

Catt - An infinity categorical coherence typechecker

Catt is an implementation of a type system checking coherences in Grothendieck-Maltsiotis infinity categories. The underlying type theoretical translation is described by Finster-Mimram.

This is my personnal implementation of this theory. For a more complete implementation, which also accounts for different flavours of semi-strict omegaècategories, check out catt.io. Older, and more experimental implementation that should be mentioned for the sake of completeness, but are now superseeded are Samuel Mimram's OCaml version, and Eric Finster's Haskell version.

There is an online version of this implementation

Syntax

There are two keywords to define a new operation

coh name ps : ty

to define a primitive coherence with arguments ps forming a pasting scheme and return type ty

let name args : ty = tm
let name args = tm

to declare an operation with arguments args and whose definition is tm, the type ty can be specified to be checked or left implicit.

Additional features

Implicit arguments

The arguments to be specified for each operation can be inferred, thus the system will always choose for you some arguments to be implicit. The chosen implicit arguments are the ones that appear explicitly in the type of further arguments. Specifically, all the arguments of definitions that appear in the types of other arguments are considered implicit by default. This can be turned off at any point with the following instruction

set explicit_substitutions = t

For instance, defining the identity, binary composition and unitor can be done as follows

coh id (x : *) : x -> x
coh comp2 (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) : x -> z
coh unit (x : *) (y : *) (f : x -> y) : comp2 f (id y) -> f

set explicit_substitutions = t
coh unit_explicit (x : *) (y : *) (f : x -> y) : comp2 x y f y (id y) -> f

Wildcards

Implicit arguments that can be inferred my be replaced by wildcards. For instance, the unitor can also be defined as For instance, defining the identity, composition and unitor can be done as follows

set explicit_substitutions = f
coh unit_wild (x : *) (y : *) (f : x -> y) : comp2 f (id _) -> f

Reduced syntax for coherence

This feature has been taken from catt.io. One can exploit the fact that pasting schemes are equivalent to well-parenthesised expressions to give a more concise syntax for them. For instance, one, can define the composition of two 1-cells as follows

coh comp2 (x(f)y(g)z) : x -> z

Internally, this reduces to contexts and are treated the same way

Suspension

Every definition can be automatically raised to a higher dimension by suspension. Formally this amounts to replacing the type of object * with an arrow type. For instance, the identity coherence on 1-cells can be defined as the suspension of the identity coherence on 0-cells. We provide a way to express this, by using the ! in front of the name to indicate that it should be suspended. Thus, the identity on 1-cells can be defined as

let id1 (x : *) (y : *) (f : x -> y) : f -> f = !id f

By default, the suspensions can be left implicit and the system will automatically insert the suspension at the right places. For instance, one can define the vertical composition of 2-cells, which is the suspension of the composition of 0-cells as follows

let vertical_comp2 (x : *) (y : *) (f : x -> y) (g : x -> y) (a : f -> g) (h : x -> y) (b : g -> h)
                  : f -> h = comp2 a b

The implicit use of suspensions can be deactivated with

set implicit_suspension = f

Functoriality of operations

All the operations that one could define are functorial, and this fact is also part of the implementation. The argument with respect to which the functoriality is applied is specified between square brackets. For instance the right whiskering can be seen as the functoriality of the composition with respect to its first argument.

let rewrite-in-comp2 (x : *) (y : *) (f : x -> y) (f' : x -> y) (a : f -> f')
                            (z : *) (g : y -> z)
	            : comp2 f g -> comp2 f' g = comp2 [a] g

One can also use fuctoriality with respect to multiple variables at the same time. For instance, the horizontal composition of two 2-cells is the functoriality of the composition with respect to both its arguments.

let rewrite-in-comp2-both (x : *) (y : *) (f : x -> y) (f' : x -> y) (a : f -> f')
                                 (z : *) (g : y -> z) (g' : y -> z) (b : g -> g')
 	            : comp2 f g -> comp2 f' g' = comp2 [a] [b]

Built-in coherences

Some useful coherences are built-in. This allows for two things: first it is not necessary as a user to define those coherences that already exist, and secondly it allows to have an internal hardcoded mechanism to manage coherence schemes instead of single coherences. The use of built-in can be deactivated via the command-line as follows catt --no-builtins [FILE] or dune exec -- catt --no-builtin [FILE]. When the use of built-in is activated, the user is prevented from defining terms or operations that have the same name as a built-in.

Compositions

The variadic compositions are defined as built-in, and named comp. In practice this means that one can write

coh unbias (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (w : *) (h : z -> w) : comp (comp f g) h -> comp f g h

Notice how the same name comp is used for the binary composition and the ternary one.

Practical use

The --debug flag

Calling catt --debug on a file will make it so that if there is an error in the file, the program will not abort, but show a menu where the user can either abort the program, ignore the error and keep checking the file, or drop in an interactive mode. For the last option, the environment of the interactive is that at the point of failure, so any coherence defined in the file causing the failure before that point is directly accessible and usable.

catt's People

Contributors

ericfinster avatar jmarkakis avatar regular-citizen avatar smimram avatar thibautbenjamin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

jmarkakis

catt's Issues

Issue when generating functorialisation

The following code:

let src (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (w : *) (h : z -> w) = comp f (comp g h)
let tgt (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (w : *) (h : z -> w) = comp (comp f g) h

coh assoc (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (w : *) (h : z -> w): src f g h ->  tgt f g h

let srcnat (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (h : y -> z) (m : g -> h) (w : *) (k : z -> w) = comp (assoc f g k) (tgt f [m] k)
let tgtnat (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (h : y -> z) (m : g -> h) (w : *) (k : z -> w) = comp (src f [m] k) (assoc f h k)

coh natassoc (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (h : y -> z) (m : g -> h) (w : *) (k : z -> w) : srcnat f m k -> tgtnat f m k

coh natnatassoc (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) (h : y -> z) (m : g -> h) (n : g -> h) (a : m -> n) (w : *) (k : z -> w) : comp (natassoc f m k) (tgtnat f [a] k) -> comp (srcnat f [a] k) (natassoc f n k)

causes catt to crash, with a WrongNumberOfArguments exception

Add iterated functorialisation

There is no obstruction to functorialise multiple times with respect to one or several variables. This should be added to the syntax. For instance, it is expected that one could write any of the following terms

  • comp[[a]] x
  • comp[[a]] [f]
  • comp [[a]] [[b]]

Add constructors for naturality

Generalised naturality terms play an important role in the theory.
Adding a constructor for them would be a first step towards a theory with better automation

Major cleanup

Lots of things need to be done:

Define an internal representation

  • define an unchecked syntax, to which the kernel syntax can export to
  • remove the explicit uses of the cut rule in the kernel and always compute down to normal forms
  • remove the need for environment variables in the kernel
  • perform the various computations in the world of the unchecked syntax
  • check the unchecked syntax to generate checked syntax in the kernel
  • elaborate the parsed syntax to the unchecked syntax/kernel syntax using the kernel API

Better management of the environment

  • Externalize the calls to the environment from the kernel

add memoization for efficiency

after merging #12

Some operations are performed several times, and one could add memoization using hashtable to reduce the cost.

  • computing a context from a pasting scheme
  • building a kernel ADT from an unchecked syntactic element

Print the name of declared lets

The code

let id (x : *) = x.

results in

=^.^= let x 
=I.I= defined term of type *.

Please indicate the name of the variable as for coherences, i.e., I would expect

=^.^= let id = x
=I.I= defined term of type *.

this would help reading the output.

Add regression tests

It would be nice to have a test suite (which would include the already fixed bugs in order to ensure that they do not reappear).

Automatically generate witnesses for equivalences

For morphisms which are equivalences, it would be nice to automatically generate "inverses" and witnesses of invertibility. Of course, this requires coming up with a decent naming scheme for those...

Add built-in coherence schemes

Some operations need to be built-in as they are used constantly. This will allow to both spare the user from defining them and hard-code some automation to make them into a scheme.

Coherence schemes that should be built-in for sure:

  • compositions (see #29): The built-in composition can be defined as a variadic operation, where we infer the arity with the number of arguments. In combination with suspensions and functorialisation (if we allow functorialising a variable several times in a go) this could produce all the possible composites that one could imagine.
  • identity (see #31): The identity is used all the time. There does not seem to be a particularly relevant scheme, and implementing it should be straightforward

One of the perks of defining these as built-ins is that we can use these built-ins as part of the generation of more complex automation, such as automation of the witnesses for equivalence (#8) and of naturality moves (#17)

Other possible built-ins:

  • associativity: is it possible to define a scheme for variadic associativity and have it infer which kind of composition it applies to? It seems doable for iterated suspensions of the composition, but will not work for the associativity of horizontal composition for instance, where we need a naturality move
  • unitors: How to indicate which unitor should be used?

In general, I do not think we should introduce built-ins requiring additional syntactic sugar, unless we have a good reason to do so. So introducing unitors and associativity in general seems a bit of a stretch, since it requires the user writing which unitor or associator they are trying to apply. However, we could introduce such things to be used inside of a context. For instance, one could probably write comp (...) (...) (eq) (...) where the keyword eq indicates that the system should infer an equivalence between the target of the previous term and the source of the next term. Ideally, those source and target are defined in the same pasting scheme, and the inferred equivalence is a single coherence. If it is not the case, then it is unclear how to proceed. We could consider the builtin eq to be a sort of tactics that may fail to infer in cases where there is not an obvious answer.

Handle implicit suspension in a more consistent way

For now implicit suspensions are handled before the constraint typing algorithm, and very hackish heuristics are used to determine how what to suspend.
This leads to some limitations, for instance, the type comp (assoc f g h) (id _)) -> id _ fails. The reason is that the identity on the RHS cannot infer that it needs a suspension.

#33 introduces constraint typing with meta type variables consistently. We could use this to determine how to implicitly supend in a more consistent way:
If the implicit suspension is activated, when we type by constraint a term of the form coh (ps,ty)[s], instead of giving the result to be ty[s], we change the base * for a meta type variable. Upon resolving, if we find this meta variable to stand for a type dimension k, we suspend the corresponding coherence k times.

Space in printing of terms

In the example

coh id (x : *) : x -> x.
let id2 (x : *) = id (id x).

the output is

=^.^= let id = x -> x
=I.I= defined.

=^.^= let (id  (id x)) 
=I.I= defined term of type (id x) -> (id x).

There are two spaces between the id on the second let, could you please remove one?

This is not for cosmetics only, it is sometimes ennoying when trying to compare types.

Add an Load/Import system

One does not want to write everything from the start all the time...
Loading file should be doable easily, and should be quick enough

Add support for holes

Often, when I construct a proof, I want to try to fill "part of the diagram". Would it be possible to add a symbol _ which would be able to take any type so that I could be able to start typing "partial morphisms" and the defined part is still typechecked?

Improve error reporting

Please improve error reporting. For instance,

coh comp (x : *) (y : *) (f : x -> y) (z : *) (g : y -> z) : x -> z.

let test (x : *) (y : *) (f : x -> y) = comp f f.

results in

=^.^= let comp = x -> z
=I.I= defined.

Fatal error: exception Common.NotEqual("x", "y")

I would expect the line and character number of the error and the fact that the second f is expected to be of type y -> ... but is of type x -> y.

Add wildcards

It should now be possible to add wildcards, in order to write things like comp f (id _)

let definitions in types

The following code

coh id (x : *) : x -> x.

let id2 (x : *) = id (id x).

let f (x : *) (g : id2 x -> id2 x) = g.

results in

Fatal error: exception Common.UnknownCoh("id2")

Add schemes for terms and coherences

Right now, one has to define all the coherences that one wants to use. It would make sense to define schemes for defining multiple related coherences at once. For instance, one could expect that it would be possible to define n-ary compositions for every n at once.

Also, the entire theory is local, every term can be put in context, and there could be a syntactic way to write that.

let definitions in let

The following code

coh id (x : *) : x -> x.

let f (x : *) =
  let i = id x in
  let j = id i in
  j.

results in

Fatal error: exception Common.UnknownId("i")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.