Практичны ли Rank2Types / RankNTypes без переменных политипов? - PullRequest
16 голосов
/ 19 июня 2010

Поскольку переменные типа не могут содержать поли-типы, кажется, что с типами Rank * мы не можем повторно использовать существующие функции из-за ограничения их монотипа.

Например, мы не можем использовать функцию (.), Когдапромежуточный тип - это политип.Мы вынуждены повторно реализовать (.) На месте.Это, конечно, тривиально для (.), Но проблема для более содержательных частей кода.

Я также думаю, что ((f. G) x) не эквивалентно (f (gx)) серьезному удару поссылочная прозрачность и ее преимущества.

Мне кажется, что это проблема с выставкой-заглушкой, и кажется, что расширения ранга * Types практически нецелесообразны для широкого использования.

Не хватаетчто-то?Есть ли план, чтобы типы ранга * лучше взаимодействовали с остальной системой типов?

РЕДАКТИРОВАТЬ: Как можно заставить типы (runST. Навсегда) работать?

Ответы [ 3 ]

11 голосов
/ 20 июня 2010

Самым последним предложением для типов ранга-N является связанная с FP статья Дона.На мой взгляд, это также самая лучшая из всех.Основная цель всех этих систем - требовать как можно меньше аннотаций типов.Проблема заключается в том, что при переходе от Хиндли / Милнера к Системе F мы теряем основные типы, и вывод типов становится неразрешимым, поэтому возникает необходимость в аннотациях типов.

Основная идея работы с "квадратными типами" заключается в распространении типованнотации, насколько это возможно.Средство проверки типа переключает режим проверки типов на вывод типов и, как мы надеемся, больше не требуется аннотаций.Недостатком здесь является то, что трудно ли объяснить аннотацию типа, потому что это зависит от деталей реализации.

Система MLF Реми до сих пор является самым хорошим предложением;он требует наименьшего количества аннотаций типов и стабилен при многих преобразованиях кода.Проблема в том, что он расширяет систему типов.Следующий стандартный пример иллюстрирует это:

choose :: forall a. a -> a -> a
id :: forall b. b -> b

choose id :: forall c. (c -> c) -> (c -> c)
choose id :: (forall c. c -> c) -> (forall c. c -> c)

Оба вышеупомянутых типа допустимы в Системе F. Первый тип является стандартным типом Хиндли / Милнера и использует предикативную реализацию, а второй использует импредикативную реализацию.Ни один тип не является более общим, чем другой, поэтому вывод типа должен был бы угадать, какой тип хочет пользователь, и это, как правило, плохая идея.

MLF вместо этого расширяет Систему F с ограниченной квантификацией.Основной (= самый общий) тип для приведенного выше примера:

choose id :: forall (a < forall b. b -> b). a -> a

Вы можете прочитать это как "choose id имеет тип a до a, где a должен быть экземпляромиз forall b. b -> b ".

Интересно, что одно это не более мощное, чем у стандартного Хиндли / Милнера.MLF, следовательно, также допускает жесткое количественное определение.Следующие два типа эквивалентны:

(forall b. b -> b) -> (forall b. b -> b)
forall (a = forall b. b -> b). a -> a

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

  • Типы могут стать труднее для чтения, потому что правая часть '<' может содержать дополнительные вложенные количественные определения. </p>

  • До недавнего времени не существовало явно выраженного варианта MLF.Это важно для типизированных преобразований компилятора (как это делает GHC).Часть 3 Кандидатская диссертация Бориса Якобовского имеет первую попытку такого варианта.(Части 1 и 2 также интересны; они описывают более интуитивное представление MLF через «Графические типы».)

Возвращаясь к FPH, его основная идея состоит в том, чтобы использовать методы MLF внутри страны., но требовать аннотации типов для привязок let.Если вам нужен только тип Хиндли / Милнера, аннотации не нужны.Если вам нужен тип с более высоким рангом, вам нужно указать запрошенный тип, но только на привязке let (или на верхнем уровне).

FPH (как MLF) поддерживает непредвиденную реализацию, поэтому я не будуне думаю, что ваша проблема применима.Поэтому не должно возникнуть никаких проблем при наборе выражения f . g выше.Однако FPH еще не реализован в GHC и, скорее всего, не будет.Трудности возникают из-за взаимодействия с принуждением к равенству (и, возможно, с ограничениями классов типов).Я не уверен, каков последний статус, но я слышал, что SPJ хочет отойти от непредсказуемости.Вся эта выразительная сила обходится дорого, и до сих пор не было найдено ни одного доступного и всеобъемлющего решения.

7 голосов
/ 19 июня 2010

Есть ли план по улучшению ранга * Типы взаимодействуют с остальной частью системы типов?

Учитывая, насколько распространена монада ST, по крайней мере типы Rank2 достаточно распространены, чтобы свидетельствовать об обратном. Тем не менее, вы можете взглянуть на серию статей "sexy / boxy types", чтобы узнать, как подходы к созданию полиморфизма произвольного ранга лучше взаимодействуют с другими.

FPH: Полиморфизм первого класса для Хаскелла , Димитриос Витиниотис, Стефани Вейрих и Саймон Пейтон Джонс, представленные в ICFP 2008.

См. Также -XImpredicativeTypes - что интересно, не рекомендуется!

6 голосов
/ 20 июня 2010

О типах Impredicative: на самом деле это не имеет значения (я относительно уверен) в вопросе спикера.Это расширение связано с типами данных.Например, GHC скажет вам, что:

Maybe :: * -> *
(forall a. a -> a) :: *

Однако это своего рода ложь.Это верно для непредсказуемой системы, и в такой системе вы можете написать:

Maybe (forall a. a -> a) :: *

, и она будет работать нормально.Это то, что позволяет ImpredicativeTypes.Без расширения подходящий способ думать об этом:

Maybe :: *m -> *m
(forall a :: *m. a -> a) :: *p

, и поэтому при попытке сформировать приложение, приведенное выше, возникает некоторое несоответствие.

GHC довольно непоследователен дляФронт непредсказуемости, хотя.Например, тип для id, который я дал выше, будет:

id :: (forall a :: *m. a -> a)

, но GHC с радостью примет аннотацию (с включенным RankNTypes, но не ImpredicativeTypes):

id :: (forall a. a -> a) -> (forall a. a -> a)

хотя forall a. a -> a не является монотипом.Таким образом, это позволит создать непредсказуемую реализацию количественных переменных, которые используются только с (->), если вы аннотируете как таковой.Но я полагаю, что это не сработает само по себе, что приводит к проблемам runST $ ....Раньше это можно было решить с помощью специального правила создания экземпляров (детали которого я никогда особо не понимал), но это правило было удалено вскоре после его добавления.

...