Полиморфизм высшего ранга является частным случаем неумышленного полиморфизма, где конструктор типа равен (->)
вместо любого произвольного конструктора, такого как []
.
Основные проблемы с непредсказуемостью состоят в том, что он делает тип проверка hard и ввод логического вывода невозможны - и действительно, мы не можем вывести типы более высокого ранга, чем 2: вы должны предоставить аннотацию типа.Это причина существования расширения Rank2Types
отдельно от RankNTypes
.Но для ограниченного случая (->)
существуют упрощенные алгоритмы для проверки этих типов и выполнения необходимого объема логического вывода для удобства программиста, такие как Полная и простая двунаправленная проверка типов для полиморфизма более высокого ранга - сравните это со сложностью Boxy Types: вывод для типов более высокого ранга и непредсказуемости .
Фактические причины в GHC отчасти исторические: там было расширение ImpredicativeTypes
, которое сейчас устарело, но оно никогда не работало должным образом или эргономично.Частично проблема заключалась в том, что у нас еще не было расширения TypeApplications
, поэтому не было удобного способа явно указать полиморфный тип в качестве аргумента типа, и компилятор попытался сделать больше вывода, чем следовало бы.Теперь, когда у нас есть TypeApplications
, ограниченная форма ImpredicativeTypes
может стать возможной в будущем.
Однако это не очень актуально, поскольку в течение некоторого времени были обходные пути: с RankNTypes
выможно «скрыть» другие формы неэффективности, обернув полиморфный тип в newtype
и явным образом упаковав и распаковав его, чтобы сообщить компилятору, где именно вы хотите обобщить и создать экземпляр переменных типа.
newtype Id = Id { unId :: forall a. a -> a }
f :: [Id]
f = [Id id] -- generalise
(unId (head f) (), unId (head f) 'x') -- instantiate to () and Char