Ну, короткая версия: Классы типов - это то, что Haskell использует для специального полиморфизма.
... но это, вероятно, ничего не прояснило для вас.
Полиморфизм должен быть знакомой концепцией для людей из ООП.Ключевым моментом здесь, однако, является разница между параметрическим и ad-hoc полиморфизмом.
Параметрический полиморфизм означает функции, которые работают с структурным типом, который сам параметризуется другими типами, такими как список значений.Параметрический полиморфизм является нормой повсюду в Хаскеле;C # и Java называют это "generics" .По сути, универсальная функция делает то же самое с определенной структурой, независимо от того, каковы параметры типа.
Специальный полиморфизм , с другой стороны, означает набор отдельных функций, делая разные (но концептуально связанные) вещи в зависимости от типов.В отличие от параметрического полиморфизма, специальные полиморфные функции необходимо указывать индивидуально для каждого возможного типа, с которым они могут использоваться. Специальный полиморфизм, таким образом, является обобщенным термином для множества функций, встречающихся в других языках, таких как перегрузка функций в C / C ++ или основанный на классах диспетчерский полиморфизм в ООП.
MajorПреимущество классов классов Хаскелла по сравнению с другими формами специального полиморфизма заключается в большей гибкости из-за , допускающего полиморфизм в любом месте сигнатуры типа .Например, большинство языков не различают перегруженные функции в зависимости от типа возвращаемого значения;классы типов могут.
Интерфейсы, которые встречаются во многих языках ООП, чем-то похожи на классы типов Хаскелла - вы указываете группу имен / сигнатур функций, которые вы хотите обрабатывать специальным полиморфным способом, а затем явноопишите, как различные типы могут использоваться с этими функциями.Классы типов в Haskell используются аналогичным образом, но с большей гибкостью: вы можете писать сигнатуры произвольных типов для функций класса типов, причем переменная типа, используемая для выбора экземпляра, будет выглядеть так: где угодно , как вам нравится, а не просто тип объекта , для которого вызываются методы.
Некоторые компиляторы Haskell, включая самый популярный, GHC, предлагают языковые расширения, которые делают классы типов еще более мощными, например multi-параметры типов параметров , которые позволяют вам выполнять специальную полиморфную диспетчеризацию функций на основе нескольких типов (аналогично тому, что называется «множественная диспетчеризация» в ООП).
Чтобы попытаться дать вам некоторое представление об этом, вот несколько смутно псевдокод с ароматом Java / C #:
interface IApplicative<>
{
IApplicative<T> Pure<T>(T item);
IApplicative<U> Map<T, U>(Function<T, U> mapFunc, IApplicative<T> source);
IApplicative<U> Apply<T, U>(IApplicative<Function<T, U>> apFunc, IApplicative<T> source);
}
interface IReducible<>
{
U Reduce<T,U>(Function<T, U, U> reduceFunc, U seed, IReducible<T> source);
}
Обратите внимание, что мы, помимо прочего, определяем интерфейс поверхуниверсальный тип и определение метода, в котором тип интерфейса отображается только как возвращаемый тип , Pure
.Не очевидно, что каждое использование имени интерфейса должно означать один и тот же тип (то есть не смешивать разные типы, которые реализуют интерфейс), но я не был уверен, как это выразить.