75
votes

I have the following two definitions that result in two different error messages. The first definition is declined because of strict positivity and the second one because of a universe inconsistency.

(* non-strictly positive *)
Inductive SwitchNSP (A : Type) : Type :=
| switchNSP : SwitchNSP bool -> SwitchNSP A.

Fail Inductive UseSwitchNSP :=
| useSwitchNSP : SwitchNSP UseSwitchNSP -> UseSwitchNSP.

(* universe inconsistency *)
Inductive SwitchNSPI : Type -> Type :=
| switchNSPI : forall A, SwitchNSPI bool -> SwitchNSPI A.

Fail Inductive UseSwitchNSPI :=
| useSwitchNSPI : SwitchNSPI UseSwitchNSPI -> UseSwitchNSPI.

Chatting on gitter revealed that universe (in)consistencies are checked first, that is, the first definition adheres this check, but then fails because of a strict positivity issue.

As far as I understand the strict positivity restriction, if Coq allows non-strictly positivity data type definitions, I could construct non-terminating functions without using fix (which is pretty bad).

In order to make it even more confusing, the first definition is accepted in Agda and the second one gives a strict positivity error.

data Bool : Set where
  True : Bool
  False : Bool

data SwitchNSP (A : Set) : Set where
  switchNSP : SwitchNSP Bool -> SwitchNSP A

data UseSwitchNSP : Set where
  useSwitchNSP : SwitchNSP UseSwitchNSP -> UseSwitchNSP

data SwitchNSPI : Set -> Set where
  switchNSPI : forall A -> SwitchNSPI Bool -> SwitchNSPI A

data UseSwitchNSPI : Set where
  useSwitchNSP : SwitchNSPI UseSwitchNSPI -> UseSwitchNSPI

Now my question is two-folded: first, what is the "evil example" I could construct with the above definition? Second, which of the rules applies to the above definition?

Some notes:

  • To clarify, I think that I do understand why the second definition is not allowed type-checking-wise, but still feel that there is nothing "evil" happening here, when the definition is allowed.
  • I first thought that my example is an instance of this question, but enabling universe polymorphism does not help for the second definition.
  • Can I use some "trick" do adapt my definition such that it is accepted by Coq?
1
Regarding Agda it's simple: Agda keeps track of polarities of parameters of data types, but not those of indices -- that's why your first definition is accepted and the second one is not, even though they're clearly isomorphic. It's just a deficiency in the type checker -- not a theoretically justified rejection.user3237465
That is, it is wrong to reject the second definition?ichistmeinname
UseSwitchNSPI does not add inconsistency to the language. I.e. if the language is consistent, then it's not possible to construct a closed proof of false having UseSwitchNSPI accepted, if that's what you're after. "wrong" is a bit strong word, there can be technical reasons not to allow UseSwitchNSPI (e.g. it might not play well with some other features of the language, might be too hard to implement, etc).user3237465
Bad phrasing from my side, but yes, that's exactly what I'm after. I didn't understand why the definition is rejected, because I couldn't construct anything "evil" with it, what I usually can, if I get a NSP-error.ichistmeinname
The bug has been fixed in Agda (cf. github.com/agda/agda/issues/3778).gallais

1 Answers

0
votes

I have the following two definitions that result in two different error messages. The first definition is declined because of strict positivity and the second one because of a universe inconsistency.

(* non-strictly positive *) Inductive SwitchNSP (A : Type) : Type := | switchNSP : SwitchNSP bool -> SwitchNSP A.

Fail Inductive UseSwitchNSP := | useSwitchNSP : SwitchNSP UseSwitchNSP -> UseSwitchNSP.

(* universe inconsistency *) Inductive SwitchNSPI : Type -> Type := | switchNSPI : forall A, SwitchNSPI bool -> SwitchNSPI A.

Fail Inductive UseSwitchNSPI := | useSwitchNSPI : SwitchNSPI UseSwitchNSPI -> UseSwitchNSPI.