Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hofmann-Streicher universes for graphs and globular types #1196

Open
wants to merge 95 commits into
base: master
Choose a base branch
from

Conversation

EgbertRijke
Copy link
Collaborator

This pull request is part of the formalization of higher category theory project with Ivan. Here we construct Hofmann-Streicher universes for:

  • directed graphs
  • reflexive directed graphs
  • globular types
  • reflexive globular types

Additionally, we add some computations for dependent Pi-types in those toposes, and some infrastructure is streamlined.

@EgbertRijke
Copy link
Collaborator Author

I have now proven the duality theorem for directed graphs (analogous to type duality), which is the toy-result of what I'm really after for globular types.

@fredrik-bakke
Copy link
Collaborator

I still find it very frustrating that pre-commit produces such a mess on commented code :(

Unfortunately, it is a choice between two evils, unless we want to start playing with making changes to the auto-formatter. Luckily your issue can be avoided by being mindful of how one comments code.

Your best course of action here is to look through the commit history for a point in time where the code wasn't jumbled. Alternatively, you could try something like text replacing -- with \n, but then you will have to manually indent things again after.

@fredrik-bakke
Copy link
Collaborator

Hiya! It looks like this PR is perhaps growing a bit outside the scope of the original goal. While I don't doubt the changes are relevant to one another, do you think it perhaps would be possible to split it up into some more manageable chunks for the eventual review?

@EgbertRijke
Copy link
Collaborator Author

There's a difference in our stylistic approaches when it comes to copattern-matched definitions that I believe we need to resolve before this PR can be merged. Otherwise, we will perpetually undo each other's work. It is my opinion that the λ where syntax is superior to our current prefix style. I have many reasons that I will try to explain to myself and you.

  1. The λ where syntax reduces verbosity in a way that, in my opinion, only improves readability. Especially for long entry names. It is my view that our current style guidelines for line wrapping and indentation are in direct conflict with the prefix copattern matching style when the entry names are long or the record is moderately nested. This entails excessive amounts of line breaks, parenthesis levels and/or indentation levels.
  2. The repetition of the entry name for every field of a record serves to add no information to a definition, and clutters the view to a problematic extent when the entry name is long.
  3. The .XXX pattern can be statically highlighted, making the code easier to read even before it typechecks (or if one doesn't use Agda's highlighting information, which you may not want to do if you're using VS Code, or if you're reading the code on GitHub).
  4. While the λ where syntax is new, I think it should be abundantly clear and intuitive to the reader after only a few exposures to it, and I don't believe it should be a point of continued confusion.

A worked-out comparison

Compare the following two equivalent pieces of Agda formalization

my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
 some-type  some-other-type ...
my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
  x =
  λ where
  .map y z 
    blablablabla x blablablablb z y
  .has-property-map w .stuff 
    blablablabla2
  .has-property-map w .structure 
    blablablabla3

to

my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
 some-type  some-other-type ...
map
  ( my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
      x)
  y z =
  blablablabla x blablablablb z y
stuff
  ( has-property-map
    ( my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
      x)
    w) =
  blablablabla2
structure
  ( has-property-map
    ( my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
      x)
    w) =
  blablablabla3

The former is clearly more readable and well-structured than the latter. Of course, you will argue that the latter should be refactored to something like the following:

module _
  (x : some-type)
  where

  map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
    some-other-type
  map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
    y z =
    blablablabla x blablablablb z y

module _
  (x : some-type) (w : ??)
  where

  stuff-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
    .....
  stuff-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    blablablabla2

  structure-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
    ....
  structure-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    blablablabla3

  has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
    ...
  stuff
    has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    stuff-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory  
  structure
    has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    structure-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory  

module _
  (x : some-type)
  where

  my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
    some-other-type ...
  map
    my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
      x
  has-property-map
    my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
      x

Which is fair, I don't argue against that. And in the process, we extract some definitions that may be useful in their own right. However, my proposed stylistic change does not conflict with this. And, it still reduces verbosity in the last two definitions:

module _
  (x : some-type) (w : ??)
  where
  
  has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
    ...
  has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    λ where
    .stuff 
      stuff-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory  
    .structure 
      structure-has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory  

module _
  (x : some-type)
  where

  my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory :
    some-other-type ...
  my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory =
    λ where
    .map 
      map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory  
        x
    .has-property-map 
      has-property-map-my-very-long-agda-entry-definition-name-that-is-very-long-and-is-in-the-namespace-of-Noncoherent-Large-Wild-Higher-Precategory
        x 

I don't understand why we can't adopt a style that affords us the option to not have to refactor every definition into its atoms every time – all while the only downside seems to be that it changes the ordering from prefix to postfix.

I think the issue I'm trying to highlight here is particularly prominent in the formalization of wild category theory and worry that the issue will grow if we do not take action to reduce the verbosity of our formalizations of wild categories.

I appreciate your point but I don't buy into the lamda-where notation as fully as you do. Our guidelines say that we prefer regular pattern matching over lambda-where patterns.

In particular in combination with coinductive types I think the lambda-where notation departs significantly from common mathematical practice, while the standard pattern matching just reads as a judgmental equality that holds when you apply a destructor to a term.

For example, the lambda-where notation permits and encourages weird looking code salads like:

λ where
  .pr1 zero-N → ...

where destructors are mixed with constructors in line of code just looks crazy, to be honest.

It is so much better to read

pr1 long-name-of-a-thing zero-N = ...

where the projection and the arguments are in a sensible order.

I think the current guidelines are sensible in not completely rejecting lambda-where notation while stating a preference for the other pattern-matching approaches. I hope too that we won't be undoing each other's work because of a difference in stylistic preferences.

EgbertRijke added a commit that referenced this pull request Nov 17, 2024
This PR should be merged before #1196.

I have only moved files and adjusted imports and markdown links
accordingly, in an attempt to preserve the credits to the content
creators.
@EgbertRijke
Copy link
Collaborator Author

I believe I've addressed all the review comments, except one where I asked if it is ok to leave it unaddressed.

@EgbertRijke EgbertRijke changed the title Hofmann-Streicher universes for graphs and globular types Towards Hofmann-Streicher universes for graphs and globular types Nov 20, 2024
@EgbertRijke EgbertRijke changed the title Towards Hofmann-Streicher universes for graphs and globular types Hofmann-Streicher universes for graphs and globular types Nov 20, 2024
Copy link
Collaborator

@fredrik-bakke fredrik-bakke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't comment without finishing my review 😩

Comment on lines 74 to 75
e₂ : {x y : G₀} {s t : H₀ x y} {u v : H₁
H₂ (refl G x) (refl G y) u v ≃ G₃ (e₁ u) (e₁ v)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is misformatted


from the image of the reflexivity cell at `x` in `G` to the reflexivity cell at
`f₀ x`, such that the [globular map](structured-types.globular-maps.md)
`f' : G' x y → H' (f₀ x) (f₀ y)` is
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, that's fine. I'll have a final read through later tonight 😁👍

record
Binary-Dependent-Globular-Type
{l1 l2 l3 l4 : Level} (l5 l6 : Level)
(G : Globular-Type l1 l2) (H : Globular-Type l3 l4) :
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason H can't be dependent over G?


A binary dependent globular type `K` over reflexive globular types `G` and `H`
is said to be
{{#concept "reflexive" Disambiguation="binary dependent globular type"}} if it
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add pointer to Agda definition

Copy link
Collaborator

@fredrik-bakke fredrik-bakke left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Crazy stuff! But next time, maybe try and keep the PR a little smaller 😬

(H : Large-Transitive-Globular-Type α2 β2)
(f : large-globular-map-Large-Transitive-Globular-Type γ G H) : UUω
where
coinductive
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This definition doesn't require the coinductive flag since it is not coinductive.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same is probably true for large ((co)lax) reflexive globular maps as well.

preserves-refl-globular-map G H (globular-map-globular-equiv e)
```

### Equivalences between globular types
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
### Equivalences between globular types
### Reflexive equivalences between reflexive globular types

- [Reflexive globular maps](globular-types.reflexive-globular-maps.md)
- [Noncoherent wild higher precategories](wild-category-theory.noncoherent-wild-higher-precategories.md)
are globular types that are both reflexive and
[transitive](globular-types.transitive-globular-types.md).
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should noncoherent wild higher precategories rather be reflexive globular types with a composition structure?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking about this, and since you're suggesting it I would be happy to make that change. I'd call them

Transitive-Reflexive-Globular-Types,

which is a bit shorter than

Noncoherent-Wild-Higher-Precategory

I've also been wondering why you use relational terminology for globular types (eg. the composition structure is called transitivity structure), but don't follow through by calling them Wild-Higher-Preorders. My explanation for this is that we probably want to convey categorical thinking rather than preorder thinking, and perhaps the terminology "preorder" in combination with "higher" would be too "wild".

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't make this change in this PR

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for the relational terminology is that I consider globular types a higher dimensional variant of graphs, as opposed to a less structured variant of categories

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't fully grasp what exactly the difference between a composition structure and transitivity is, though I expect it will be immediately clear if I try and apply the concept, so my question was genuinely "is transitivity the wrong concept?"

@EgbertRijke
Copy link
Collaborator Author

Crazy stuff! But next time, maybe try and keep the PR a little smaller 😬

You're right. Sorry!

Thanks so much for reviewing this beast!

@fredrik-bakke
Copy link
Collaborator

Sorry to rush you, but could we try to get this PR merged? The outstanding comments are very minor, and I'd like to continue work on wild higher categories.

@fredrik-bakke
Copy link
Collaborator

I wouldn't mind making the final fixes without credit so we could get this PR merged, for instance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants