Конструктор кортежей Haskell (GHC) и разделение между языком и его реализацией - PullRequest
35 голосов
/ 17 августа 2011

Хаскелл снова взорвал мой разум, когда я понял, что

(x,y)

Это просто синтаксический сахар для

(,) x y

Естественно, я хотел расширить это на более крупные кортежи. Но

(,) x ((,) y z)

дал мне

(x,(y,z))

Что было не то, что я искал. По своей прихоти я попробовал

(,,) x y z

И это сработало, давая именно то, что я хотел:

(x,y,z)

Это подняло вопрос: как далеко вы можете взять это? К моему удивлению, казалось, что нет предела. Все перечисленные ниже являются действительными операторами:

(,)
(,,)
(,,,)
(,,,,)
--etc
(,,,,,,,,,,,,,,)
(,,,,,,,,,,,,,,,)
--etc
(,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)
--etc

Такое поведение поразительно и приводит к моему актуальному вопросу: можно ли имитировать что-то в моих собственных функциях? Или это просто особенность GHC оператора кортежа? Я думаю, что это последнее, поскольку я прочитал спецификацию haskell98 и в iirc сказано, что реализации должны определять оператор кортежа только для 15 элементов. Принимая во внимание, что GHC прошел всю борьбу и позволил вам сделать это до произвольных пределов.

Итак, возможно ли определить это семейство операторов / функций из самой реализации haskell, используя только систему типов и существующие языковые функции (объявления, сигнатуры типов, определения функций и т. Д.)? И если да, то как? Или это невозможно, и вместо этого вам нужно заглянуть в компилятор, чтобы найти поддерживающую среду для этого набора функций?

Это приводит к еще более общему вопросу: какая часть Haskell поддерживается самим Haskell через определения типов и функций, объявления и т. Д .; и сколько поддерживается компилятором / реализацией? (Я знаю, что GHC был написан на Хаскеле, это не отвечает на вопрос)

То есть, если бы вы отказались от стандартных библиотек (включая прелюдию) и делали все с нуля в необработанном Haskell; Можно ли построить полную реализацию, которая имеет все функции GHC, используя только этот минимальный набор функций? Каков минимальный набор языковых возможностей, которые вам нужны для создания реализации на Haskell с использованием Haskell? Смогу ли я отказаться от прелюдии и затем полностью перестроить ее вручную изнутри GHC? Если вы откажетесь от прелюдии и никогда ничего не импортируете, с чем вам еще предстоит работать?

Может показаться, что я задаю миллион вопросов, но на самом деле все они пытаются задать одно и то же с другой формулировкой. Сделай свой лучший снимок ТАК!

1 Ответ

38 голосов
/ 17 августа 2011

Увы, в кортежах нет магии. Вот реализация, которую GHC использует , и чтобы дать вам некоторое представление о том, что происходит, вот источник для последнего определения:

data (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__
  = (,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) a b c d e f g h i j k l m n o p q r s t u v w x y z a_ b_ c_ d_ e_ f_ g_ h_ i_ j_ k_ l_ m_ n_ o_ p_ q_ r_ s_ t_ u_ v_ w_ x_ y_ z_ a__ b__ c__ d__ e__ f__ g__ h__ i__ j__

... да.

Итак, возможно ли определить это семейство операторов / функций из самой реализации haskell, используя только систему типов и существующие языковые функции (объявления, сигнатуры типов, определения функций и т. Д.)?И если да, то как?Или это невозможно, и вместо этого вам нужно заглянуть в компилятор, чтобы найти вспомогательную среду для этого набора функций?

Нет, нет способа определить кортежи подобным образом в общем виде.Общий шаблон является чисто синтаксическим, ничего, что нельзя сделать рекурсивно в системе типов или иным образом.Вы можете сгенерировать такие определения, используя Template Haskell, конечно, но вы все равно будете генерировать каждое из них отдельно с помощью манипуляции со строками для создания имени, без использования какой-либо общей структуры.

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

data Tuple2 a b = Tuple2 a b
data Tuple3 a b c = Tuple3 a b c

... и т. Д., Которые не используют специальный синтаксис, но по-прежнему не могут быть определены в общем по указанным выше причинам.

Это приводит к еще более общему вопросу: какая часть Haskell поддерживается самим Haskell через определения типов и функций, объявления и т. Д .;и сколько поддерживается компилятором / реализацией?(Я знаю, что GHC был написан на Хаскеле, который не отвечает на вопрос)

Почти все это определено в Хаскеле.Некоторые вещи имеют специальный синтаксис, который вы не можете имитировать, но в большинстве случаев он распространяется только на то, что компилятор уделяет особое внимание определенным определениям.В противном случае нет никакой разницы между this :

data [] a = [] | a : [a]

... и любым эквивалентным типом, который вы определяете сами.

То есть, если бы выотказаться от стандартных библиотек (включая прелюдию) и делать все с нуля на простом Хаскеле;Можно ли построить полную реализацию, которая имеет все функции GHC, используя только этот минимальный набор функций?Каков минимальный набор языковых возможностей, которые вам нужны для создания реализации на Haskell с использованием Haskell?Смогу ли я отказаться от прелюдии, а затем полностью перестроить ее вручную из GHC?Если вы откажетесь от прелюдии и никогда ничего не импортируете, что вам остается для работы?

Вам может показаться полезным прочитать о расширениях GHC NoImplicitPrelude и RebindableSyntax , которыеПозвольте вам, среди прочего, изменить определения, используемые для интерпретации записи do, обработки числовых литералов, синтаксиса if then else и т. д.

Достаточно сказать, что очень, очень мало можетне будет переопределено.Большинство вещей, которые не могут быть только специальными из-за синтаксиса, и могут быть заменены эквивалентными вещами (например, списки и кортежи, выше).

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

...