2011-01-04 1 views
5

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

В макропроцессоре пользователь может написать эту функцию, потому что кортежи - это списки.

Для функций в карри, пользователь может легко писать трансформаторы, поскольку этот термин является двоичным как на целевом, так и на представлении Ocaml этого термина и набрав.

Но они не могут сделать это для кортежей. Вот еще один пример: пользователь легко определяет оператор серийной функциональной композиции. Но пользователь не может определить параллельный состав: бинарная версия:

f1: D1 -> C1, f2: D2-> C2 --> f1 * f2: D1 * D2 -> C1 * C2 

легко написано, но не может быть продлен до 3-х условиях: здесь складка бы вычислить

f1 * (f2 * f3) 

вместо

f1 * f2 * f3 

[изоморфно, но не равно]

Обобщение этого вопроса: «Как мне внедрить полиадический язык программирования ", который слишком много, чтобы спросить здесь. То, что я пытался сделать, это обеспечить встроенный трансформатор:

карри: T1 * T2 * T3 ... -> T1 -> T2 -> ... uncurry: T1 -> T2 -> .. T1 * T2 * T3

так, то пользователь просто может сделать сгибы с бинарным оператором:

uncurry (fold user_op (uncurry term)) 

, но это не является ни достаточно универсален и не работает так хорошо .. :)

Я думаю, эквивалентный вопрос для Haskell было бы: поскольку Haskell не имеет n-арных продуктов, конструкторы n-ary tuple моделируются в th e библиотека с n функциями, каждая из которых должна быть выписана вручную. Это явно отстой. Как это будет исправлено?

[Я имею в виду, это тривиально, чтобы написать сценарий Python для создания этих п функций вплоть до некоторого предела п, так почему это так трудно сделать это в хорошо напечатанные образом внутри язык?]

ответ

2

есть два компонента, которые сотрудничают, чтобы вызвать эту проблему:

  • кортежей автоматически не сплющенный - скобки в выражениях типа сделать больше, чем группы, они создают различные типы, которые соединены дополнительными кортежи. Это приводит к вашему наблюдению, что a * (b * c) изоморфен, но не эквивалентен a * b * c.
  • Система типов не предоставляет средства для выражения алгебры по типам кортежей. Под этим я подразумеваю, что система типов не имеет оператора cons или любого эквивалента для кортежей; нет никакого способа выразить, что тип имеет больше или меньше элементов с чередованием, чем другой тип.

В результате не существует способа выразить тип функции, которая работает с кортежами произвольной длины.

Итак, краткое изложение состоит в том, что система типа OCaml не имеет механизмов для выражения типа функции, которую вы пытаетесь написать, и, следовательно, вы не можете написать функцию (отбросив неприятные игры с помощью Obj; вы можете написать функцию , но вы не можете выразить свой тип, чтобы использовать его безопасным образом).

+2

Да, но это не мой вопрос: я не спрашиваю о том, что делает система типа Ocaml, я спрашиваю, как реализовать это на другом языке (мой язык Felix на самом деле, компилятор для которого написан в Ocaml). – Yttrill

0

Существует в основном два варианта.

Вы можете сделать свой язык не типичным или слабо типизированным. Например, в C кортежи (целые числа, скажем) могут быть представлены как int*. Что-то нужно будет отслеживать длины кортежей, но система типа не будет. Я полагаю, вы не хотите идти именно так.

Для типа безопасного языка вам нужна очень выразительная система типов. А именно, вам нужны типы, зависящие от значений. Участниками которых являются функции, возвращающие типы. Например, конструктор типа кортежа (не путать с конструктором кортежа) может иметь тип tuple : int -> Type -> Type. Операция, которая расширяет кортеж, может иметь тип forall n:int. forall T:Type. tuple n T -> T -> tuple (n+1) T. Такие системы типов стоят дорого: обычно вывод типа не рекурсивный, и проверка типов разрешима только в том случае, если вы готовы аннотировать все виды подвыражений с их типом (аннотации в вышеприведенных частях forall являются лишь намеком на то, что влекут за собой.). Эти варианты кажутся излишними, если все, что вы хотите достичь, это полиадность.

Отказ от ответственности: Мое знание теории типов немного устарело.

+0

Вы правы, я не хочу слабой печати. Однако мне не нравится вывод типа, поэтому мне все равно, что типизация должна быть явной. Я думаю, что полностью зависимая типизация будет чрезмерной. Даже на языке ATS Hongwei Xi) вскоре стало видно, что, когда кто-то пытается выходить далеко за рамки простых линейных целочисленных формул, проверка доказательств непрактична, если не является неразрешимой. – Yttrill

+0

BTW: досадно, что вы действительно можете делать такие вещи довольно легко без проверки типов: на C++ с шаблонами и на схеме. Моя система в Felix могла на самом деле делать кортежи, она просто не работает с массивами (которые идентичны кортежам с общим типом элемента). Но нужно гораздо больше, чем просто противников и бессовцев. С GADT я могу сделать больше. Но эта коллекция интересных функций - это просто хаки. Это не общее. Тем не менее я могу легко что-то сделать, просто используя Python для «печати» кода, который я хочу. – Yttrill

+0

BTW: Я думаю, что есть альтернатива зависимой типизации (типы в зависимости от значений), которая является мета-типизацией (kinding). Например, массив длины 5 в Феликсе уже является типом T^5, где 5 представляет собой сумму из 5 единиц 1 + 1 + 1 + 1 + 1, где 1 - тип «единица» значения(). Таким образом, если бы существовал вид «Unitsum», то кортеж: int -> Type -> Type был бы перезаписан tuple: Unitsum -> Type -> type, который больше не требует зависимого набора текста, а вместо него - системы подбора. – Yttrill