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

structure sometimes makes a Type not a Prop. #2690

Closed
1 task done
kbuzzard opened this issue Oct 15, 2023 · 6 comments · Fixed by #5517
Closed
1 task done

structure sometimes makes a Type not a Prop. #2690

kbuzzard opened this issue Oct 15, 2023 · 6 comments · Fixed by #5517
Labels
bug Something isn't working

Comments

@kbuzzard
Copy link
Contributor

Prerequisites

  • Put an X between the brackets on this line if you have done all of the following:
    • Check that your issue is not already filed.
    • Reduce the issue to a minimal, self-contained, reproducible test case. Avoid dependencies to mathlib4 or std4.

Description

Structures which should be Props (because all their fields are Props) sometimes come out as Types and Lean needs to be explicitly told that they are Props.

Steps to Reproduce

structure foo (α : Type) where
  h : ∀ a : α, a = a

#check foo Nat -- Type?!

structure foo' (α : Type) : Prop where
  h : ∀ a : α, a = a

#check foo' Nat -- Prop, as expected

Expected behavior:

foo α : Prop

Actual behavior:

foo α : Type

Versions

This bug has existed since Lean 3 and the community has been using the obvious workaround for years ("when you randomly notice an instance of this, typically because a new user is confused on Zulip, just tell the structure that it's a Prop explicitly")

[Output of lean --version in the folder that the issue occured in]

Lean (version 4.2.0-rc1, commit a62d2fd, Release)

[OS version]

Ubuntu 22.04

Impact

Very minor, occasionally confusing, little more than annoying once you know about it.

Add 👍 to issues you consider important. If others are impacted by this issue, please ask them to add 👍 to it.

@arthur-adjedj
Copy link
Contributor

arthur-adjedj commented Oct 16, 2023

Looking into the related implementation, this seems to be an intended design decision and not a bug. In particular, some classes such as Decidable and IsNeutral make use of the fact that the universe infered is Type. This issue probably deserves to be tagged as an RFC.

@digama0
Copy link
Collaborator

digama0 commented Oct 16, 2023

Decidable would not infer Prop type, and it's not a structure in the first place. IsNeutral can and should be a Prop.

Looking into the related implementation, this seems to be an intended design decision and not a bug.

I don't see how you can read intentionality into that uncommented code. Certainly this is the function that would need to be changed and it does not do what is suggested in this issue, but there is no indication that this is a deliberate design or that it is not written in this way to avoid a certain other issue.

@arthur-adjedj
Copy link
Contributor

arthur-adjedj commented Oct 16, 2023

I first experimented with having the same rules apply to both inductives and inductives (it was also easier to do so since they shared the same bit of code), IsNeutral is composed with an Option here, hence the need to either have it in Type, or lift the universe it. I didn't experiment further down that path, but assumed other such issues would come up.

I don't see how you can read intentionality into that uncommented code.

That bit of code seems to have been made with the purpose of making things live in Type as a fallback. If it didn't, the code could simply be Level.mkNaryMax us.toList |>.normalize here, hence why I assumed it was a thought out decision.

@digama0
Copy link
Collaborator

digama0 commented Oct 16, 2023

Things should live in Type as a fallback. But the fallback doesn't need to be taken if there is <= 1 constructor and all the constructor arguments are Props or recursive, since then it would be a large eliminating type even if it lived in Prop.

@arthur-adjedj
Copy link
Contributor

That was my reasoning as well, but that would change not only the type of structures, but also of a lot of inductives, so I'm hesitant on doing that.

@digama0
Copy link
Collaborator

digama0 commented Oct 16, 2023

IsNeutral is composed with an Option here, hence the need to either have it in Type, or lift the universe it. I didn't experiment further down that path, but assumed some other issues would come up.

I'm inclined to lift the universe using Nonempty there. The impact is relatively minimal, but it is sufficiently unrelated to the PR that it might be worth doing separately.

kmill added a commit to kmill/lean4 that referenced this issue Sep 29, 2024
…c subsingletons

A `Prop`-valued inductive type is a syntactic subsingleton if it has at most one constructor and all the arguments to the constructor are in `Prop`. Such types have large elimination, so they could be defined in `Type` or `Prop` without any trouble, though users tend to expect that such types define a `Prop` and need to learn to insert `: Prop` manually.

Currently, the default universe for types is `Type`. This PR adds a heuristic: if a type is a syntactic subsingleton with exactly one constructor, and the constructor has at least one parameter, then the `inductive` command will prefer creating a `Prop` instead of a `Type`. For `structure`, we ask for at least one field.

More generally, for mutual inductives, each type needs to be a syntactic subsingleton, at least one type must have one constructor, and at least one constructor must have at least one parameter.

Thanks to @arthur-adjedj for the investigation in leanprover#2695.

Closes leanprover#2690
kmill added a commit to kmill/lean4 that referenced this issue Oct 8, 2024
…c subsingletons

A `Prop`-valued inductive type is a syntactic subsingleton if it has at most one constructor and all the arguments to the constructor are in `Prop`. Such types have large elimination, so they could be defined in `Type` or `Prop` without any trouble, though users tend to expect that such types define a `Prop` and need to learn to insert `: Prop` manually.

Currently, the default universe for types is `Type`. This PR adds a heuristic: if a type is a syntactic subsingleton with exactly one constructor, and the constructor has at least one parameter, then the `inductive` command will prefer creating a `Prop` instead of a `Type`. For `structure`, we ask for at least one field.

More generally, for mutual inductives, each type needs to be a syntactic subsingleton, at least one type must have one constructor, and at least one constructor must have at least one parameter.

Thanks to @arthur-adjedj for the investigation in leanprover#2695.

Closes leanprover#2690
github-merge-queue bot pushed a commit that referenced this issue Oct 8, 2024
…c subsingletons (#5517)

A `Prop`-valued inductive type is a syntactic subsingleton if it has at
most one constructor and all the arguments to the constructor are in
`Prop`. Such types have large elimination, so they could be defined in
`Type` or `Prop` without any trouble, though users tend to expect that
such types define a `Prop` and need to learn to insert `: Prop`.

Currently, the default universe for types is `Type`. This PR adds a
heuristic: if a type is a syntactic subsingleton with exactly one
constructor, and the constructor has at least one parameter, then the
`inductive` command will prefer creating a `Prop` instead of a `Type`.
For `structure`, we ask for at least one field.

More generally, for mutual inductives, each type needs to be a syntactic
subsingleton, at least one type must have one constructor, and at least
one constructor must have at least one parameter. The motivation for
this restriction is that every inductive type starts with a zero
constructors and each constructor starts with zero fields, and
stubbed-out types shouldn't be `Prop`.

Thanks to @arthur-adjedj for the investigation in #2695 and to @digama0
for formulating the heuristic.

Closes #2690
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
3 participants