Наследование классов типов разных типов в Coq

Это своего рода продолжение моего предыдущего вопроса: Наследование нескольких классов типов в Coq , но речь идет о классах типов, которые ожидают разные типы (в терминах Haskell, я полагаю?).

У меня есть класс типов Collection, который ожидает Type -> Type, и класс типов Monoid, который ожидает Type, и я думал, что знаю, как согласовать их оба, но у меня проблемы с использованием функций 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".

Я думал, что был действительно умен, выясняя, что (forall A, S A) в наследовании Monoid, но теперь я не так уверен. Тип 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

person user2063685    schedule 01.01.2015    source источник


Ответы (2)


После нескольких дней работы над этой проблемой я получил наследование классов типов различных типов, что, насколько я могу судить, является правильным.

Я был на правильном пути в обновлении своего вопроса. Все, что мне нужно было сделать, это добавить явное наследование Semigroup. Я до сих пор не уверен, почему он должен быть явным, если наследование из коллекции неявно наследует от складываемого и разворачиваемого. Может быть, это из-за всего наследства.

Кроме того, я узнал, что включение функций в объявление типа неверно или, по крайней мере, не нужно. Я выяснил, прочитав статью автора классов типов в Coq и Coq справочное руководство. (Если вы прокрутите вниз до класса типов 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.

Спасибо за помощь, Перс. Звучит грубо, но ваш ответ был настолько разочаровывающим, что мне пришлось выяснить, ошибались ли вы на самом деле. :)

person user2063685    schedule 10.01.2015

Нет, моноид - это конкретный 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;
}.
person Perce Strop    schedule 02.01.2015
comment
Итак, вы говорите, что мне придется объявлять экземпляры List nat и List Bool как моноиды по отдельности? Это похоже на серьезный ущерб для создания полезных классов типов, поэтому я действительно не хочу вам верить. Не могли бы вы дать больше информации о том, почему вы уверены, что классы типов работают именно так в Coq? - person user2063685; 05.01.2015
comment
@ user2063685 Я не очень разбираюсь в классах типов и не могу указать вам на какие-либо проекты, но я предполагаю, что вам нужно это сделать. Я также предполагаю, что вы получаете сообщение об ошибке, потому что вы подсчитываете более A. Может быть, кто-то еще должен это прокомментировать. Здесь или в списке рассылки Coq. - person Perce Strop; 05.01.2015