Jump to content

Тип класса

В информатике класс типов — это конструкция системы типов , поддерживающая специальный полиморфизм . Это достигается за счет добавления ограничений на переменные типа в параметрически полиморфных типах. Такое ограничение обычно включает класс типа T и переменная типа aи означает, что a может быть создан только тип, члены которого поддерживают перегруженные операции, связанные с T.

Классы типов были впервые реализованы на языке программирования Haskell после того, как их впервые предложили Филип Уодлер и Стивен Блотт в качестве расширения «eqtypes» в Standard ML . [1] [2] способ реализации перегруженных арифметических операций и операторов равенства . и изначально были задуманы как принципиальный [3] [2] В отличие от «eqtypes» Standard ML, перегрузка оператора равенства посредством использования классов типов в Haskell не требует обширной модификации интерфейса компилятора или базовой системы типов. [4]

Обзор [ править ]

Классы типов определяются путем указания набора имен функций или констант вместе с соответствующими типами, которые должны существовать для каждого типа, принадлежащего классу. В Haskell типы можно параметризовать; класс типа Eq предназначенный для содержания типов, допускающих равенство, будет объявлен следующим образом:

class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool

где a является одним экземпляром класса типа Eq, и a определяет сигнатуры функций для двух функций (функций равенства и неравенства), каждая из которых принимает два аргумента типа a и вернуть логическое значение.

Переменная типа a имеет вид ( также известен как Type в последней версии GHC ), [5] означает, что вид Eq является

Eq :: Type -> Constraint

Объявление можно прочитать как указание «типа a принадлежит классу типов Eq если есть функции с именем (==), и (/=), соответствующих типов, определенных на нем». Затем программист может определить функцию elem (который определяет, находится ли элемент в списке) следующим образом:

elem :: Eq a => a -> [a] -> Bool
elem y []     = False
elem y (x:xs) = (x == y) || elem y xs

Функция elem имеет тип a -> [a] -> Bool с контекстом Eq a, который ограничивает типы, которые a может варьироваться от тех a которые принадлежат к Eq тип класса. ( Примечание : Хаскель => можно назвать «ограничением класса».)

Программист может сделать любой тип t член данного класса типов C используя объявление экземпляра , которое определяет реализации всех C' методы для конкретного типа t. Например, если программист определяет новый тип данных t, они могут затем сделать этот новый тип экземпляром Eq предоставляя функцию равенства значений типа t любым способом, который они считают нужным. Как только они это сделают, они могут использовать функцию elem на [t], то есть списки элементов типа t.

Обратите внимание, что классы типов отличаются от классов объектно-ориентированных языков программирования. В частности, Eq не является типом: не существует такого понятия, как значение типа. Eq.

Классы типов тесно связаны с параметрическим полиморфизмом. Например, обратите внимание, что тип elem как указано выше, это будет параметрически полиморфный тип. a -> [a] -> Bool если бы не ограничение класса типа " Eq a =>".

Полиморфизм высшего рода [ править ]

Класс типа не обязательно должен принимать переменную типа вида Type но могу взять любой. Эти классы типов более высоких типов иногда называются классами-конструкторами (конструкторы, о которых идет речь, являются конструкторами типов, такими как Maybe, а не конструкторы данных, такие как Just). Примером является Monad сорт:

class Monad m where
  return :: a -> m a
  (>>=)  :: m a -> (a -> m b) -> m b

Тот факт, что m применяется к переменной типа, указывает на то, что она имеет вид Type -> Type, то есть он принимает тип и возвращает тип, вид Monad таким образом:

Monad :: (Type -> Type) -> Constraint

Классы типов с несколькими параметрами [ править ]

Классы типов допускают несколько параметров типа, поэтому классы типов можно рассматривать как отношения к типам. [6] Например, в стандартной библиотеке GHC класс IArray выражает общий интерфейс неизменяемого массива. В этом классе ограничение класса типа IArray a e означает, что a это тип массива, который содержит элементы типа e. (Это ограничение на полиморфизм используется для реализации неупакованных , например, типов массивов.)

Как мультиметоды [ нужна ссылка ] классы типов с несколькими параметрами поддерживают вызов различных реализаций метода в зависимости от типов нескольких аргументов и типов возвращаемых значений. Классы типов с несколькими параметрами не требуют поиска метода для каждого вызова во время выполнения; [7] : минута 25:12 скорее вызываемый метод сначала компилируется и сохраняется в словаре экземпляра класса типа, как и в случае с классами типов с одним параметром.

Код Haskell, использующий классы типов с несколькими параметрами, не является переносимым, поскольку эта функция не является частью стандарта Haskell 98. Популярные реализации Haskell, GHC и Hugs , поддерживают классы типов с несколькими параметрами.

Функциональные зависимости [ править ]

В Haskell классы типов были усовершенствованы, чтобы позволить программисту объявлять функциональные зависимости между параметрами типа — концепция, вдохновленная теорией реляционных баз данных . [8] [9] То есть программист может утверждать, что данное присвоение некоторого подмножества параметров типа однозначно определяет остальные параметры типа. Например, общая монада m который несет параметр состояния типа s удовлетворяет ограничению класса типа Monad.State s m. В этом ограничении существует функциональная зависимость m -> s. Это означает, что для данной монады m типа класса Monad.State, тип состояния, доступный из m определяется однозначно. Это помогает компилятору в выводе типа , а также помогает программисту в типизированном программировании .

Саймон Пейтон-Джонс возражал против введения функциональных зависимостей в Haskell по причине сложности. [10]

Классы типов и неявные параметры [ править ]

Классы типов и неявные параметры очень похожи по своей природе, хотя и не совсем одинаковы. Полиморфная функция с ограничением класса типа, например:

sum :: Num a => [a] -> a

можно интуитивно рассматривать как функцию, которая неявно принимает экземпляр Num:

sum_ :: Num_ a -> [a] -> a

Экземпляр Num_ a по сути, это запись, содержащая определение экземпляра Num a. (Фактически именно так классы типов реализуются под капотом компилятора Glasgow Haskell.)

Однако есть принципиальная разница: неявные параметры более гибкие — вы можете передавать разные экземпляры. Num Int. Напротив, классы типов реализуют так называемое свойство согласованности , которое требует, чтобы для любого данного типа был только один уникальный выбор экземпляра. Свойство когерентности делает классы типов в некоторой степени антимодульными, поэтому настоятельно не рекомендуется использовать потерянные экземпляры (экземпляры, определенные в модуле, который не содержит ни класс, ни интересующий тип). С другой стороны, согласованность добавляет языку дополнительный уровень безопасности, давая программисту гарантию того, что две непересекающиеся части одного и того же кода будут использовать один и тот же экземпляр. [11]

Например, упорядоченный набор (типа Set a) требует полного упорядочения элементов (типа a), чтобы функционировать. Об этом может свидетельствовать ограничение Ord a, который определяет оператор сравнения элементов. Однако существует множество способов навести полный порядок. Поскольку алгоритмы множеств обычно нетерпимы к изменениям порядка после создания набора, передача несовместимого экземпляра Ord a к функциям, которые работают на наборе, может привести к неверным результатам (или сбоям). Таким образом, обеспечение согласованности Ord a в этом конкретном сценарии имеет решающее значение.

Экземпляры (или «словари») в классах типов Scala — это просто обычные значения языка, а не совершенно отдельный вид сущностей. [12] [13] Хотя эти экземпляры по умолчанию предоставляются путем поиска соответствующих экземпляров в области видимости, которые будут использоваться в качестве неявных фактических параметров для явно объявленных неявных формальных параметров, тот факт, что они являются обычными значениями, означает, что они могут быть предоставлены явно, чтобы устранить неоднозначность. В результате классы типов Scala не удовлетворяют свойству связности и фактически являются синтаксическим сахаром для неявных параметров.

Это пример из группы Cats. [14] документация:

// A type class to provide textual representation
trait Show[A] {
  def show(f: A): String
}

// A polymorphic function that works only when there is an implicit 
// instance of Show[A] available
def log[A](a: A)(implicit s: Show[A]) = println(s.show(a))

// An instance for String
implicit val stringShow = new Show[String] {
  def show(s: String) = s
}

// The parameter stringShow was inserted by the compiler.
scala> log("a string")
a string

Coq (версия 8.2 и более поздние) также поддерживает классы типов, выводя соответствующие экземпляры. [15] Последние версии Agda 2 также предоставляют аналогичную функцию, называемую «аргументами экземпляра». [16]

к перегрузке Другие подходы операторов

В Standard ML механизм «типов равенства» примерно соответствует встроенному классу типов Haskell. Eq, но все операторы равенства автоматически выводятся компилятором. Контроль над процессом со стороны программиста ограничивается указанием того, какие компоненты типов в структуре являются типами равенства, а переменные каких типов в диапазоне полиморфных типов превышают типы равенства.

Модули и функторы SML и OCaml могут играть роль, аналогичную роли классов типов Haskell, причем принципиальным отличием является роль вывода типа, что делает классы типов пригодными для специального полиморфизма. [17] Объектно-ориентированное подмножество OCaml — это еще один подход, который в некоторой степени сравним с подходом к классам типов.

Связанные понятия [ править ]

Аналогичным понятием для перегруженных данных (реализованным в GHC ) является семейство типов . [18]

В C++, в частности, в C++20 имеется поддержка классов типов с использованием Concepts (C++) . В качестве иллюстрации приведенный выше пример класса типов Eq на Haskell можно записать как

template <typename T>
concept Equal =
      requires (T a, T b) {
            { a == b } -> std::convertible_to<bool>;
            { a != b } -> std::convertible_to<bool>;
};

Классы типов в Clean похожи на Haskell, но имеют немного другой синтаксис.

Rust поддерживает типажи , которые представляют собой ограниченную форму согласованных классов типов. [19]

В Mercury есть классы типов, хотя они не совсем такие, как в Haskell. [ нужны дальнейшие объяснения ]

В Scala классы типов — это идиома программирования , которая может быть реализована с использованием существующих функций языка, таких как неявные параметры, а не отдельной функции языка как таковой. Благодаря тому, как они реализованы в Scala, в случае неоднозначности можно явно указать, какой экземпляр класса типа использовать для типа в определенном месте кода. Однако это не обязательно является преимуществом, поскольку экземпляры классов неоднозначных типов могут быть подвержены ошибкам.

Помощник по доказательству Coq также поддерживает классы типов в последних версиях. В отличие от обычных языков программирования, в Coq любые законы класса типов (например, законы монады), изложенные в определении класса типов, должны быть математически доказаны для каждого экземпляра класса типов перед их использованием.

См. также [ править ]

Ссылки [ править ]

  1. ^ Моррис, Джон Г. (2013). Классы типов и цепочки экземпляров: реляционный подход (PDF) (доктор философии). Департамент компьютерных наук Портлендского государственного университета. дои : 10.15760/etd.1010 .
  2. Перейти обратно: Перейти обратно: а б Вадлер, П.; Блотт, С. (1989). «Как сделать специальный полиморфизм менее специальным» . Материалы 16-го симпозиума ACM SIGPLAN-SIGACT по принципам языков программирования (POPL '89) . Ассоциация вычислительной техники. стр. 60–76. дои : 10.1145/75277.75283 . ISBN  0897912942 . S2CID   15327197 .
  3. ^ Каес, Стефан (март 1988 г.). «Параметрическая перегрузка в полиморфных языках программирования». Учеб. 2-й Европейский симпозиум по языкам программирования . дои : 10.1007/3-540-19027-9_9 .
  4. ^ Аппель, AW; МакКуин, Д.Б. (1991). «Стандартный ML Нью-Джерси». В Малушиньском, Дж.; Вирсинг, М. (ред.). Реализация языка программирования и логическое программирование. ПЛИЛП 1991 . Конспекты лекций по информатике. Том. 528. Спрингер. стр. 1–13. CiteSeerX   10.1.1.55.9444 . дои : 10.1007/3-540-54444-5_83 . ISBN  3-540-54444-5 .
  5. ^ Type от Data.Kind появился в версии 8 компилятора Glasgow Haskell
  6. ^ Haskell Страница MultiParamTypeClasses .
  7. ^ В GHC ядро ​​C использует сигнатуры типов System F Girard & Reynold для идентификации типизированного случая для обработки на этапах оптимизации. -- Саймон Пейтон-Джонс « В ядро ​​— сжатие Haskell в девять конструкторов» Конференция пользователей Erlang, 14 сентября 2016 г.
  8. ^ Джонс, Марк П. (2000). «Тип-классы с функциональными зависимостями» . В Смолке Г. (ред.). Языки и системы программирования. ЭСОП 2000 . Конспекты лекций по информатике. Том. 1782. Спрингер. стр. 230–244. CiteSeerX   10.1.1.26.7153 . дои : 10.1007/3-540-46425-5_15 . ISBN  3-540-46425-5 .
  9. ^ Haskell Страница FunctionalDependities .
  10. ^ Пейтон-Джонс, Саймон (2006). «MPTC и функциональные зависимости» . Список рассылки Haskell-prime .
  11. ^ Кметт, Эдвард. Классы типов против всего мира . Бостонская встреча Haskell. Архивировано из оригинала 21 декабря 2021 г.
  12. ^ Оливейра, Бруно CdS; Мавр, Адриан; Одерский, Мартин (2010). «Классы типов как объекты и неявные выражения» (PDF) . Материалы Международной конференции ACM по языкам и приложениям объектно-ориентированных систем программирования (OOPSLA '10) . Ассоциация вычислительной техники. стр. 341–360. CiteSeerX   10.1.1.205.2737 . дои : 10.1145/1869459.1869489 . ISBN  9781450302036 . S2CID   207183083 .
  13. ^ «Руководство для неофитов по Scala, часть 12: Классы типов — Дэниел Вестхайде» .
  14. ^ typelevel.org, Scala Cats
  15. ^ Кастеран, П.; Созо, М. (2014). «Нежное введение в классы типов и отношения в Coq» (PDF) . CiteSeerX   10.1.1.422.8091 .
  16. ^ « Моделирование классов типов с аргументами экземпляра ».
  17. ^ Дрейер, Дерек; Харпер, Роберт; Чакраварти, Мануэль М.Т. (2007). «Классы модульных типов». Материалы 34-го ежегодного симпозиума ACM SIGPLAN-SIGACT по принципам языков программирования (POPL '07) . стр. 63–70. См. стр. 63. дои : 10.1145/1190216.1190229 . ISBN  978-1595935755 . S2CID   1828213 . ТР-2006-03.
  18. ^ «Семейства GHC/Type — HaskellWiki» .
  19. ^ Турон, Аарон (2017). «Специализация, согласованность и эволюция API» .

Внешние ссылки [ править ]

Arc.Ask3.Ru: конец переведенного документа.
Arc.Ask3.Ru
Номер скриншота №: cb76e122eda4c1901a0ae1cbef48c17a__1699808100
URL1:https://arc.ask3.ru/arc/aa/cb/7a/cb76e122eda4c1901a0ae1cbef48c17a.html
Заголовок, (Title) документа по адресу, URL1:
Type class - Wikipedia
Данный printscreen веб страницы (снимок веб страницы, скриншот веб страницы), визуально-программная копия документа расположенного по адресу URL1 и сохраненная в файл, имеет: квалифицированную, усовершенствованную (подтверждены: метки времени, валидность сертификата), открепленную ЭЦП (приложена к данному файлу), что может быть использовано для подтверждения содержания и факта существования документа в этот момент времени. Права на данный скриншот принадлежат администрации Ask3.ru, использование в качестве доказательства только с письменного разрешения правообладателя скриншота. Администрация Ask3.ru не несет ответственности за информацию размещенную на данном скриншоте. Права на прочие зарегистрированные элементы любого права, изображенные на снимках принадлежат их владельцам. Качество перевода предоставляется как есть. Любые претензии, иски не могут быть предъявлены. Если вы не согласны с любым пунктом перечисленным выше, вы не можете использовать данный сайт и информация размещенную на нем (сайте/странице), немедленно покиньте данный сайт. В случае нарушения любого пункта перечисленного выше, штраф 55! (Пятьдесят пять факториал, Денежную единицу (имеющую самостоятельную стоимость) можете выбрать самостоятельно, выплаичвается товарами в течение 7 дней с момента нарушения.)