Функциональный язык можно рассматривать как категорию, где его объектами являются типы и функции морфизмов между ними.
Как классы типов вписываются в эту модель?
Я предполагаю, что мы должны рассматривать только те реализации, которые удовлетворяют ограничению, которое имеет большинство классов типов, но которые не выражены в Haskell. Например, мы должны рассматривать только те реализации, Functor
для которых fmap id ≡ id
и fmap f . fmap g ≡ fmap (f . g)
.
Или есть какие-то другие теоретические основы для классов типов (например, основанные на типизированных лямбда-исчислениях)?
Ответы:
Короткий ответ: они этого не делают.
Всякий раз, когда вы вводите в язык принуждения, классы типов или другие механизмы для специального полиморфизма, основной проблемой проектирования, с которой вы сталкиваетесь, является согласованность .
По сути, вам нужно убедиться, что разрешение класса типов является детерминированным, чтобы у хорошо типизированной программы была единственная интерпретация. Например, если бы вы могли дать несколько экземпляров для одного и того же типа в одной и той же области, вы могли бы потенциально написать неоднозначные программы, подобные этой:
В зависимости от выбора экземпляра, который делает компилятор,
blah v
может равняться либо либо,"Hello"
либо"Goodbye"
. Следовательно, смысл программы не будет полностью определяться синтаксисом программы, а скорее может зависеть от произвольного выбора, который делает компилятор.Решение этой проблемы в Haskell состоит в том, чтобы каждый тип имел не более одного экземпляра для каждого класса типов. Чтобы обеспечить это, он разрешает объявления экземпляров только на верхнем уровне и, кроме того, делает все объявления глобально видимыми. Таким образом, компилятор всегда может сообщить об ошибке, если сделано неоднозначное объявление экземпляра.
Однако объявление глобально видимым нарушает композиционную семантику. Что вы можете сделать для восстановления, так это дать семантику разработки для языка программирования - то есть вы можете показать, как переводить программы на Haskell в язык с хорошим поведением и композиционным языком.
На самом деле это также дает вам возможность компилировать классы типов - обычно это называется «преобразованием доказательств» или «преобразованием словаря» в кругах Haskell и является одним из ранних этапов большинства компиляторов Haskell.
Классы типов также являются хорошим примером того, как дизайн языка программирования отличается от теории чистого типа. Классы типов - действительно потрясающая особенность языка, но они довольно плохо себя ведут с точки зрения теории доказательств. (Вот почему Agda вообще не имеет классов типов и почему Coq делает их частью своей инфраструктуры эвристического вывода.)
источник