这是我上一个问题的后续问题:Multiple Typeclass Inheritance in Coq,但这是关于期望不同种类的类型类型(用Haskell术语,我猜?)。
我有一个类型类Collection,它需要一个Type -> Type
和一个类型类Monoid,它需要一个Type
,而且我认为我知道如何调和它们,但我和#39;我在使用Monoid函数时遇到问题。
Class Sequence (S : Type -> Type)
foldr empty insert append
`{C : Collection S foldr empty insert}
`{M : Monoid (forall A, S A) append empty} :=
{
insert_append_id :
forall (A : Type) (h : S A) (x : A),
append A (insert A x (empty A)) h = insert A x h
}.
(裁减)错误是:
Error:
In environment
Sequence :
forall (S : Type -> Type)
(append : (forall A : Type, S A) ->
(forall A : Type, S A) -> forall A : Type, S A)
[...]
S : Type -> Type
empty : forall A : Type, S A
append :
(forall A : Type, S A) -> (forall A : Type, S A) -> forall A : Type, S A
[...]
M : Monoid (forall A : Type, S A) append empty
A : Type
h : S A
x : A
The term "A" has type "Type" while it is expected to have type
"forall A : Type, S A".
我认为我非常聪明,想要在Monoid继承中获得(forall A, S A)
,但现在我不太确定。 Monoid empty
的类型看起来是正确的,但append
的类型对我没有任何意义。
在我看来,我或者使用Monoid继承类型犯了一个错误,或者有一些方法可以添加我没有看到的正确类型。或者在其他地方是否存在导致此问题的错误?
<小时/>
编辑:我想出了一个看起来更接近我想要的Monoid声明,但仍然不起作用。
Class Sequence (S : Type -> Type)
foldr empty insert (append : forall A, S A -> S A -> S A)
`{C : Collection S foldr empty insert}
`{M : forall (A : Type), Monoid (S A) (append A) (empty A)} :=
{
insert_append_eq :
forall (A : Type) (h : S A) (x : A),
append A (insert A x (empty A)) h = insert A x h
}.
新错误:
Error:
Could not find an instance for "Semigroup (S A) (append A)" in environment:
S : Type -> Type
foldr : forall A B : Type, (A -> B -> B) -> B -> S A -> B
empty : forall A : Type, S A
insert : forall A : Type, A -> S A -> S A
append : forall A : Type, S A -> S A -> S A
F : Foldable S foldr
U : Unfoldable S empty insert
C : Collection S foldr empty insert
A : Type
答案 0 :(得分:1)
在对这个问题进行了几天的讨论之后,我有不同类型的类型类继承,据我所知,这是正确的。
我在问题更新中走在正确的轨道上。我需要做的就是添加Semigroup的显式继承。我仍然不确定为什么它从collection继承隐式继承可折叠和可展开时必须是显式的。也许这是因为作为遗产的一部分。
另外,我了解到包含类型声明中的函数是不正确的,或者至少是不必要的。我通过阅读Coq和Coq paper中类词类作者的reference manual找到了。 (如果向下滚动到EqDec
类型类,则会在大括号中看到eqb
已键入。)
所以,这就是我的Sequence类型类现在的样子:
Class Sequence (S : Type -> Type)
`{C : Collection S}
`{G : forall (A : Type), Semigroup (S A)}
`{M : forall (A : Type), Monoid (S A)} :=
{
insert_append_eq :
forall (A : Type) (h : S A) (x : A),
op (insert A x (empty A)) h = insert A x h
}.
为了确保这实际上正确创建了类型类,我定义了一个List类型并使其成为Sequence的一个实例。不幸的是,这涉及首先使它成为每个父类型类的实例。我想知道是否有更简单的方法。
并且只是包含更多代码示例,因为我发现它们比自然语言解释更容易理解,这里是我的Semigroup类型类和它的List实例:
Class Semigroup (S : Type) :=
{
op :
S -> S -> S;
semigroup_assoc :
forall x y z : S,
op x (op y z) = op (op x y) z
}.
Inductive List (A : Type) : Type :=
| Nil : List A
| Cons : A -> List A -> List A
.
Instance semigroup_list : forall A, Semigroup (List A) :=
{
op := fix append l l' :=
match l with
| Nil => l'
| Cons x xs => Cons A x (append xs l')
end
}.
Proof.
intros.
induction x.
apply eq_refl.
rewrite IHx.
apply eq_refl.
Defined.
感谢你的帮助,Perce。这听起来很有意思,但你的答案是如此令人失望,我不得不弄清楚你是否真的错了。 :)
答案 1 :(得分:0)
不,幺半群是应用于特定S
的特定A
。你不能进一步概括它。下面的代码应该可以工作,虽然我无法测试它。
Class Sequence (S : Type -> Type) (A : Type)
foldr empty insert append
`{C : Collection S foldr empty insert}
`{M : Monoid (S A) (append A) (empty A)} :=
{
insert_append_id :
forall (h : S A) (x : A),
append _ (insert _ x (empty _)) h = insert _ x h
}.
或者,您可以使用不同类型的幺半群。
Class Mon (F : Type -> Type) (mul : forall X, F X -> F X -> F X)
(one : forall X, F X) : Type :=
{
idl : forall X x, mul X (one X) x = x;
idr : forall X x, mul X x (one X) = x;
asc : forall X x y z, mul X x (mul X y z) = mul X (mul X x y) z;
}.