Syntax error: '.' expected after [vernac:gallina] (in [vernac_aux]) in Coq when using inductive with integers

huangapple go评论58阅读模式
英文:

Syntax error: '.' expected after [vernac:gallina] (in [vernac_aux]) in Coq when using inductive with integers

问题

"Syntax error: '.' expected after [vernac:gallina] (in [vernac_aux])." -> "语法错误:在 [vernac:gallina] 中期望'.'。"

英文:

So I'm trying to define an inductive set in coq that has integers from 0 to 10:

Inductive OD : Set := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10.

I get this message:

Syntax error: '.' expected after [vernac:gallina] (in [vernac_aux]).

Nothing I tried has really worked

答案1

得分: 1

Unfortunately the parser is expecting a constructor not a number after :=. You can bypass this using Notation.

Inductive OD : Set := N0 | N1 | N2 | N3 | N4 | N5 | N6 | N7 | N8 | N9 | N10.

Notation "0" := N0.
Notation "1" := N1.
Notation "2" := N2.
Notation "3" := N3.
Notation "4" := N4.
Notation "5" := N5.
Notation "6" := N6.
Notation "7" := N7.
Notation "8" := N8.
Notation "9" := N9.
Notation "10" := N10.
英文:

Unfortunately the parser is expecting a constructor not a number after :=. You can bypass this using Notation.

Inductive OD : Set := N0 | N1 | N2 | N3 | N4 | N5 | N6 | N7 | N8 | N9 | N10.

Notation "0" := N0.
Notation "1" := N1.
Notation "2" := N2.
Notation "3" := N3.
Notation "4" := N4.
Notation "5" := N5.
Notation "6" := N6.
Notation "7" := N7.
Notation "8" := N8.
Notation "9" := N9.
Notation "10" := N10.

答案2

得分: 0

你的问题涉及不同性质的对象。当你说“一个归纳类型,包含从0到10的整数”时,实际上描述的是一种不可能的情况。

归纳类型的本质是,它们的元素与任何其他类型的元素都不同。因此,你可以决定定义一个包含十一个元素的归纳类型,以一种方式命名,使其提醒人们0到10的11个整数,但你希望定义的这个新的归纳类型实际上并不包含这些整数。换句话说,整数0到10不是这种类型的成员。

因此,第一个解决方案是Lolo在另一个答案中提出的解决方案,如下所示:

Inductive OD : Set := N0 | N1 | N2 | N3 | N4 | N5 | N6 | N7 | N8 | N9 | N10.

然而,元素N0N10不是整数,它们是类型OD的元素。你不能在需要整数的操作中使用它们。

这是类型理论(Type Theory)与集合论(set theory)之间的固有差异,类型理论是Coq系统的基础理论,而人们在进行数学实践时通常使用的是集合论。

为了减小类型OD与整数之间的差距,有另一种方法,不同于上面显示的表示方法。我们可以提供类型整数和类型OD之间的强制转换。以下是我的解决方案:

Open Scope Z.

Definition Z_of_OD (x : OD) :=
  match x with
  N0 => 0 
  | N1 => 1 
  | N2 => 2 
  | N3 => 3 
  | N4 => 4 
  | N5 => 5 
  | N6 => 6 
  | N7 => 7 
  | N8 => 8 
  | N9 => 9 
  | N10 => 10
  end.

Coercion Z_of_OD : OD >-> Z.

Check ( 135 + N0).

Definition OD_of_Z (x : Z) :=
  match x with
  0 => N0 
  | 1 => N1 
  | 2 => N2 
  | 3 => N3 
  | 4 => N4 
  | 5 => N5 
  | 6 => N6 
  | 7 => N7 
  | 8 => N8 
  | 9 => N9 
  | _ => N10
  end.

Coercion OD_of_Z : Z >-> OD.

Check 8 : OD.

正如你可以看到的,通过这两个Check命令,你现在有了一个包含11个元素的类型OD,它关联到整数(但它们不是整数),这要归功于提供的两个强制转换Z_of_ODOD_of_Z。借助这些强制转换,任何整数都可以视为OD的元素,整数范围外的整数被映射到N10。因此,你可以在期望整数的地方使用类型OD的对象,也可以在期望OD的元素的地方使用类型Z的对象。

在实际应用中,Coq系统保持了这种区别,所以OD没有整数010,但在日常使用中,这模拟了你想要的效果,我相信。

例如,你可以定义一个将OD的元素映射到循环的后继的函数。

Definition OD_succ (x : OD) :=
  match x with
  N0 => N1
  | N1 => N2
  | N2 => N3
  | N3 => N4
  | N4 => N5
  | N5 => N6
  | N6 => N7
  | N7 => N8
  | N8 => N9
  | N9 => N10
  | N10 => N0
  end.

函数OD_succ需要一个类型为OD的参数,并返回类型OD的结果,但我们可以编写以下表达式:

Compute (1 + OD_succ 10).

这返回1,因为:

  • 10不是类型为OD的,所以10被替换为OD_of_Z 10
  • OD_of_Z计算为N0
  • OD_succ (OD_of_Z 10)不是整数,因此不能在整数操作中使用,它被替换为Z_of_OD (OD_succ (OD_of_Z 10)
  • Z_of_OD (OD_succ (OD_of_Z 10)的计算返回整数0
  • 1 + 0的计算返回整数1。

另一方面,如果要求

Compute OD_succ 10.

结果具有类型OD,显示为N0。因此,Coq系统保持了类型之间的区别。这些强制转换只是使这种区别更加方便。

英文:

Your question mixes objects of a different nature. When you say "an inductive type that has integers from 0 to 10", you are actually describing a situation that is impossible.

It is the nature of inductive types that their elements are distinct from elements of any other types. So you can decide to define an inductive with eleven elements, named in a way that reminds of the 11 integers 0 to 10, but this new inductive you wish to define does not have these integers. In other words, the integers 0 to 10 are not members of this type.

So a first solution is the one presented by Lolo in a different answer, repeated here:

Inductive OD : Set := N0 | N1 | N2 | N3 | N4 | N5 | N6 | N7 | N8 | N9 | N10.

However, the elements N0.. N10 are not integers, they are elements of type OD. You cannot use them in operations that require integers.

This an inherent difference between Type Theory, the theory that underlies the Coq system and set theory, the theory that people are accustomed to use when performing practicing mathematics.

To reduce the gap between type OD and integers, there is another approach than the notation approach shown above. We can provide coercions between the type of integers and and the type OD. Here is my solution:

Open Scope Z.

Definition Z_of_OD (x : OD) :=
  match x with
  N0 => 0 
  | N1 => 1 
  | N2 => 2 
  | N3 => 3 
  | N4 => 4 
  | N5 => 5 
  | N6 => 6 
  | N7 => 7 
  | N8 => 8 
  | N9 => 9 
  | N10 => 10
  end.

Coercion Z_of_OD : OD >-> Z.

Check ( 135 + N0).

Definition OD_of_Z (x : Z) :=
  match x with
  0 => N0 
  | 1 => N1 
  | 2 => N2 
  | 3 => N3 
  | 4 => N4 
  | 5 => N5 
  | 6 => N6 
  | 7 => N7 
  | 8 => N8 
  | 9 => N9 
  | _ => N10
  end.

Coercion OD_of_Z : Z >-> OD.

Check 8 : OD.

As you can see with the two Check commands, you now have a type OD containing 11 elements, which associated to integers (but they are not integers) thanks to the two provided coercions Z_of_OD and OD_of_Z. Thanks to these coercions, any integer can be viewed as an element of OD, the integers that are outside the range of OD being mapped to N10. So you can use an object of type OD where you would expect an integer and you can use an object of type Z where you would expect an element of OD.

In practice, the Coq system maintain the distinction, so that OD does not have the integers 0 to 10, but in day-to-day usage, this simulates what you want, I believe.

For instance you can define a function that maps the elements of OD to a circular notion of successor.

Definition OD_succ (x : OD) :=
  match x with
  N0 => N1
  | N1 => N2
  | N2 => N3
  | N3 => N4
  | N4 => N5
  | N5 => N6
  | N6 => N7
  | N7 => N8
  | N8 => N9
  | N9 => N10
  | N10 => N0
  end.

The function OD_succ requires an argument of type OD and returns a result in type OD, but we can write the following expression:

Compute (1 + OD_succ 10).

This returns 1 because

  • 10 is not of type OD, so 10 is replaced by OD_of_Z 10
  • OD_of_Z computes to N0
  • OD_succ (OD_of_Z 10) is not an integer, so it cannot be used in an integer operation, it is replaced by Z_of_OD (OD_succ (OD_of_Z 10)
  • the computation of Z_of_OD (OD_succ (OD_of_Z 10) returns the integer 0
  • the computation of 1 + 0 returns the integer 1.

On the other hand, if require

Compute OD_succ 10.

The result has type OD and is displayed as N0. So the distinction between types is maintained by the Coq system. The coercions simply makes this distinction more comfortable to live with.

This approach still has some drawbacks, for instance, we need a little more work to talk about the subset of integers that corresponds to OD, but there are other solutions for this. If you want to go in that direction, I suggest you study the treatment of finite types and intial segments of the natural numbers (named ordinal types) in the library mathematical components

huangapple
  • 本文由 发表于 2023年4月20日 05:56:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76059096.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定