Я видел много частичных определений «истинного полиморфизма», например Вот а также Вот но нигде не удалось найти четкого примера различия с двумя конкретными примерами.
Я понимаю, что перегрузка +
Оператор — это некая форма полиморфизма, и она реализована по-разному в Haskell и C ++. Может кто-то точно показать, в чем разница с примерами на обоих языках?
Вы ищете термин «параметрический полиморфизм», который отличается от «специального полиморфизма».
Примером параметрического полиморфизма является сигнатура типа для Nothing
:
Nothing :: Maybe a
a
в типе может быть любой мыслимый тип, так как Nothing
населяет все Maybe
s. Мы говорим, что a
является параметрически полиморфным, потому что это может быть любой тип.
Теперь рассмотрим этот тип:
Just 1 :: (Num b) => Maybe b
На этот раз b
не может быть любого типа: это может быть только тип, который является экземпляром Num
, Мы говорим, что b
является специальным полиморфным, потому что это может быть любой член набора типов, заданных экземплярами Num
учебный класс.
Итак, резюмируем:
Параметрический полиморфизм: может быть любого типа
Специальный полиморфизм: ограниченный типом класса
Есть три типа полиморфизма, с которыми вы часто сталкиваетесь (на примерах C ++ и Haskell).
Параметрический полиморфизм в функциональных языках это особенность систем типов, где типом функции является выражение, выраженное количественно по переменным типа. Типы ввода ограничивают свободные параметры в сигнатуре, которая определяет тип вывода. Например, функция map принимает функцию в качестве первого аргумента, который определяет тип списка ввода и списка вывода.
map :: (a -> b) -> [a] -> [b]
На языке теории типов подпись часто пишется:
∀ a. ∀ b. (a -> b) -> [a] -> [b]
C ++ может достигать эффектов параметрического полиморфизма с помощью шаблонов, но, на мой взгляд, очень хрупок (т.е. приводит к неопределенным ошибкам компиляции) и не имеет формализма, обнаруженного в найденных функциональных языках:
template <class T>
T add(T a, T b) {
return a+b;
}
Специальный полиморфизм это когда функции с одинаковыми именами действуют по-разному, когда «просматриваются» с разными сигнатурами типов. В Хаскеле это выражается классами типов. Тип a
в подписи за (+)
ограничен типами, которые реализуют Num
тип класс.
(+) :: Num a => a -> a -> a
class Num a where
(+) :: a -> a -> a
instance Num Int where
(+) = plusInt
Подтип полиморфизма. Не присутствует в Haskell, но другие языки (Scala, ML) имеют полиморфизм подтипа. В объектно-ориентированных языках это обычно языковая функция, где разные экземпляры объектов реализуют вызовы метода или свойства с одинаковым именем и отправляются в зависимости от семантики объектной модели. В C ++ например:
class Animal {
public:
virtual void speak() = 0;
};
class Cat : public Animal {
public:
void speak() {
printf("Meow");
}
};
class Dog : public Animal {
public:
void speak() {
printf("Woof");
}
};
Что нужно помнить о полиморфизме, так это отделить основную идею от реализации. Например, специальный полиморфизм — это не то же самое, что классы типов, это всего лишь одно из его выражений.