在Coq中继承不同类型的类别

时间:2015-01-01 22:36:31

标签: typeclass coq type-kinds

这是我上一个问题的后续问题: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

2 个答案:

答案 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;
}.