这是一个人为的多类型列表:
Inductive Apple : Set :=.
Inductive Pear : Set :=.
Inductive FruitList : Set :=
| Empty
| Cons_apple (a : Apple) (p : FruitList)
| Cons_pear (p : Pear) (p: FruitList).
Variable a : Apple.
Variable p : Pear.
Definition a_fruitList := Cons_apple a (Cons_pear p Empty).
有没有办法为此定义列表表示法,例如,a_fruitList
可以由[p,a]
定义?
答案 0 :(得分:3)
问题是你的列表有两个cons构造函数,而递归表示法的通常表示法机制要求你总是使用相同的构造函数。强制可以帮助您克服部分问题:
Section ApplesAndPears.
Variable Apple Pear : Set.
Inductive FruitList : Set :=
| Nil
| ConsApple (a : Apple) (l : FruitList)
| ConsPear (p : Pear) (l : FruitList).
Inductive Fruit : Set :=
| IsApple (a : Apple)
| IsPear (p : Pear).
Coercion IsApple : Apple >-> Fruit.
Coercion IsPear : Pear >-> Fruit.
Definition ConsFruit (f : Fruit) (l : FruitList) : FruitList :=
match f with
| IsApple a => ConsApple a l
| IsPear p => ConsPear p l
end.
Notation "[ ]" := (Nil) (at level 0).
Notation "[ x ; .. ; y ]" := (ConsFruit x .. (ConsFruit y Nil) ..) (at level 0).
Variable a : Apple.
Variable p : Pear.
Definition a_fruitList := [ a ; p ].
End ApplesAndPears.
(顺便说一句,我假设你真的打算写[ a ; p ]
,而不是[ p ; a ]
。如果你的意思是写[ p ; a ]
,那么你只需要使用而是一个SnocFruit
函数,它将元素添加到列表的末尾。但是,这会使后面解释的问题更加严重。)
现在,我们已经定义了一个替换构造函数的新函数,并且可以通过将Fruit
的构造函数声明为强制来使用该函数。
当然,这个解决方案并不完全令人满意,因为你的符号产生的术语引用ConsFruit
,而理想情况下,选择ConsApple
或ConsFruit
的内容会很好取决于你给出的论点。我怀疑用符号机制没有办法做到这一点,但我可能是错的。
这是我建议您仅使用list
类型并声明其他类型(例如Fruit
)以保留Apple
和Pear
而非使用两个cons构造函数,除非你有充分的理由不这样做。
答案 1 :(得分:3)
正如Arthur Azevedo De Amorim所提到的,问题是Coq的Notation
机制没有考虑子表达式的类型来区分Cons_apple
和{{1} }。但是,您可以使用Type Classes执行此操作:
Cons_pear
我们在这里定义了一个包含单个函数的类型类Class Cons_fruit(A:Set) := {
CONS: A -> FruitList -> FruitList }.
Instance Cons_fruit_apple: Cons_fruit Apple:= { CONS := Cons_apple }.
Instance Cons_fruit_pear: Cons_fruit Pear := { CONS := Cons_pear }.
Notation " [ x ; .. ; y ] " := (CONS x .. (CONS y Empty) .. ).
Definition test := [a; p; p; a ].
,以及两个实例,一个用于处理苹果,一个用于处理梨。然后我们可以在表示法中使用模板化的CONS函数,Coq将在需要时选择适当的实例。
请注意,这可能会导致错误消息的可理解性降低。例如,
Cons_fruit
你会得到
Definition bad:= [ 0; p ].
答案 2 :(得分:-1)
以下是Coq关于lists
的文档摘录Notation " [ ] " := nil : list_scope.
Notation " [ x ] " := (cons x nil) : list_scope.
Notation " [ x ; .. ; y ] " := (cons x .. (cons y nil) ..) : list_scope.
我会坚持使用;
而不是,
,因为后者通常用于Coq的语法,因此正确获取符号优先级可能很棘手。
最佳,
诉P>