#functional-programming #scope #typeclass #coq
#функциональное программирование #область применения #класс типов #coq
Вопрос:
Я могу наивно построить иерархию алгебраических структур в Coq, используя классы типов. У меня возникли некоторые проблемы с поиском ресурсов по синтаксису и семантике Coq для классов типов. Однако я считаю, что следующая правильная реализация полугрупп, моноидов и коммутативных моноидов:
Class Semigroup {A : Type} (op : A -> A -> A) : Type := {
op_associative : forall x y z : A, op x (op y z) = op (op x y) z
}.
Class Monoid `(M : Semigroup) (id : A) : Type := {
id_ident_left : forall x : A, op id x = x;
id_ident_right : forall x : A, op x id = x
}.
Class AbelianMonoid `(M : Monoid) : Type := {
op_commutative : forall x y : A, op x y = op y x
}.
Если я правильно понимаю, дополнительные параметры (например, идентификационный элемент моноида) можно добавить, сначала объявив Monoid
экземпляр Semigroup
, а затем параметризируя on id : A
. Однако в записи, созданной для, происходит что-то странное AbelianMonoid
.
< Print Monoid.
Record Monoid (A : Type) (op : A -> A -> A) (M : Semigroup op)
(id : A) : Type := Build_Monoid
{ id_ident_left : forall x : A, op id x = x;
id_ident_right : forall x : A, op x id = x }
< Print AbelianMonoid.
Record AbelianMonoid (A : Type) (op : A -> A -> A)
(M0 : Semigroup op) (id0 : A) (M : Monoid M0 id0) :
Type := Build_AbelianMonoid
{ op_commutative : forall x y : A, op x y = op y x }
Это произошло, когда я пытался создать класс для полугрупп. Я думал, что следующий синтаксис был правильным:
Class Semiring `(P : AbelianMonoid) `(M : Monoid) := {
...
}.
Однако я не смог удалить правильные операторы и элементы идентификации. Печать записей выявила проблемы, описанные выше. Итак, у меня два вопроса: во-первых, как мне правильно объявить класс Monoid
; во-вторых, как мне устранить неоднозначность функций в суперклассах?
Что мне действительно хотелось бы, так это хорошие ресурсы, которые четко объясняют классы типов Coq без устаревшего синтаксиса. Например, я думал, что книга Хаттона ясно объясняет классы типов в Haskell.
Комментарии:
1. Если вы не делаете это в качестве учебного упражнения, возможно, вам захочется проверить библиотеку математических классов (которой также могло не быть, когда вы спрашивали об этом) github.com/math-classes/math-classes
Ответ №1:
Список литературы:
Каноническими ссылками на классы типов в Coq — помимо руководства — являются эта статья и тезис (на французском языке) Матье Созо. В недавней статье и в моей диссертации меньше канонических ссылок (с разными точками зрения) на уровне исследований. Вам также следует потратить некоторое время на канал #coq на Freenode и подписаться на список рассылки.
Ваша проблема:
Проблема синтаксиса заключается не в Classes
per se, а в максимально вставленных неявных аргументах. Monoid
Типы AbelianMonoid
and имеют в вашем определении (неявные) параметрические аргументы, которые в этом порядке являются типом домена, операцией и идентификатором — как индексируется зависимым продуктом, который вы видите полностью развернутым при печати этих типов записей. Они заполняются автоматически, когда вы упоминаете зависимый продукт без его аргументов в позиции, где они понадобились бы.
Действительно, неявное разрешение аргументов автоматически вставит требуемые параметрические аргументы, которые будут идентичными (для обоих продуктов, которые зависят от них: P
и M
‘s типы), если оставить их на своих собственных устройствах. Вам просто нужно указать ограничения между этими идентификаторами, указав переменные для различных идентификаторов, разные, когда это необходимо :
Class Semiring A mul add `(P : AbelianMonoid A mul) `(M : Monoid A add) := {
}.
Результат :
> Print Semiring.
Record Semiring (A : Type) (mul add : A -> A -> A)
(M0 : Semigroup mul) (id0 : A) (M : Monoid M0 id0)
(P : AbelianMonoid M) (M1 : Semigroup add) (id1 : A)
(M : Monoid M1 id1) : Type := Build_Semiring { }
For Semiring: Arguments M0, id0, M, M1, id1 are implicit and maximally
inserted
For Semiring: Argument scopes are [type_scope _ _ _ _ _ _ _ _ _]
For Build_Semiring: Argument scopes are [type_scope _ _ _ _ _ _ _ _ _]
Обратите внимание, что тождества для абелевых моноидов и моноидов на этот раз различны. Это хорошее упражнение (даже если оно имеет мало математического смысла), чтобы научить себя писать тип записи (он же класс), который вы бы хотели, если бы у вас был один и тот же элемент идентификатора для аддитивной и мультипликативной структур.
Комментарии:
1. Спасибо за ссылки на Созо и Оури. Их статьи выглядят полезными и информативными, и, вероятно, на данный момент их достаточно. Я уверен, что мне и другим будет полезен ваш тезис, если вы захотите опубликовать его, как только он достигнет завершенного состояния. Учитывая ваш ответ, я чувствую, что ознакомление с зависимыми записями прояснило бы реализацию Coq классов типов.