Полиморфизм высшего ранга чрезвычайно полезен. В System F (основной язык типизированных языков FP, с которым вы знакомы), это важно для принятия «типизированных кодировок Церкви», что фактически делает System F программированием. Без них система F совершенно бесполезна.
В системе F мы определяем числа как
Nat = forall c. (c -> c) -> c -> c
Дополнение имеет тип
plus : Nat -> Nat -> Nat
plus l r = Λ t. λ (s : t -> t). λ (z : t). l s (r s z)
который является типом более высокого ранга ( forall c.появляется внутри этих стрелок).
Это встречается и в других местах. Например, если вы хотите указать, что вычисление является правильным стилем передачи продолжения (google "codensity haskell"), то вы должны исправить это как
type CPSed A = forall c. (A -> c) -> c
Даже разговор о необитаемом типе в System F требует более высокого ранга полиморфизма
type Void = forall a. a
Короче говоря, написание функции в системе чистого типа (System F, CoC) требует более высокого ранга полиморфизма, если мы хотим иметь дело с любыми интересными данными.
В частности, в Системе F эти кодировки должны быть «непредсказуемыми». Это означает, что forall a.количественно определяет абсолютно все типы . Это включает в себя тот самый тип, который мы определяем. В forall a. aэтом на aсамом деле может стоять forall a. aснова! В таких языках, как ML, это не так, их называют «предикативными», поскольку переменная типа количественно определяет только набор типов без квантификаторов (называемых монотипами). Наше определение plusтребуемого impredicativity, а потому , что мы создания экземпляра cв l : Natбыть Nat!
Наконец, я хотел бы упомянуть одну последнюю причину, по которой вам нужны как непредсказуемость, так и полиморфизм более высокого ранга даже в языке с произвольно рекурсивными типами (в отличие от System F). В Haskell есть монада для эффектов, называемая «монадой потока состояний». Идея состоит в том, что монада потока состояний позволяет вам мутировать вещи, но требует экранирования, чтобы ваш результат не зависел от чего-либо изменяемого. Это означает, что вычисления ST являются чисто наблюдаемыми. Для выполнения этого требования мы используем полиморфизм более высокого ранга
runST :: forall a. (forall s. ST s a) -> a
Здесь, гарантируя, что aэто ограничено пределами области, в которой мы представляем s, мы знаем, что aозначает хорошо сформированный тип, на который не полагаются s. Мы используем sдля параметризации всех изменяемых вещей в этом конкретном потоке состояний, чтобы мы знали, что aэто не зависит от изменяемых вещей и, таким образом, ничто не выходит за рамки этих STвычислений! Прекрасный пример использования типов для исключения некорректных программ.
Кстати, если вы заинтересованы в изучении теории типов, я бы предложил инвестировать в хорошую книгу или две. Трудно выучить этот материал по частям. Я бы предложил одну из книг Пирса или Харпера по теории PL в целом (и некоторые элементы теории типов). Книга "Расширенные темы по типам и языкам программирования" также охватывает большое количество теории типов. Наконец, «Программирование в теории типов Мартина Лофа» является очень хорошим изложением теории интенсиональных типов, изложенной Мартином Лофом.
let sdff = (g : (f : <T> (e : T) => void) => void) => {}