Этот ответ в ответ на вопросы, воспитанных illissius, точка за точкой:
- Это некрасиво использовать. $ (fooBar '' Asdf) просто не выглядит красиво. Поверхностно, конечно, но это способствует.
Я согласен. Мне кажется, что $() выбрано так, чтобы выглядеть как часть языка - используя знакомый поддон Haskell. Тем не менее, это именно то, что вы/не хотите/не хотите в символах, используемых для сращивания макросов. Они определенно сливаются в слишком много, и этот косметический аспект очень важен. Мне нравится внешний вид {{}} для сращиваний, потому что они довольно визуально различны.
- Это даже уродливее, чтобы писать. Иногда цитаты работают, но в то же время вы должны выполнять ручную трансплантацию АСТ и сантехнику. [API] [1] большой и громоздкий, всегда есть много случаев, о которых вам неинтересно, но их еще нужно отправить, а случаи, о которых вы заботитесь, обычно присутствуют в нескольких похожих, но не идентичных формах (данные vs newtype, стиль записи и обычные конструкторы и т. д.). Это скучно и повторяемо, чтобы писать и усложнять, чтобы не быть механическим. [Предложение по реформированию] [2] затрагивает некоторые из этих вопросов (более широко применимые котировки).
Я также согласен с этим, однако, так как некоторые из комментариев в «Новые направления TH» наблюдать, отсутствие хорошего из-из-коробки AST цитируйте не является критическим недостатком.В этом пакете WIP я пытаюсь решить эти проблемы в библиотечной форме: https://github.com/mgsloan/quasi-extras. До сих пор я разрешаю сращивание в нескольких местах, чем обычно, и может сопоставлять образцы по AST.
- Сценическое ограничение - это ад. Невозможность сплайсинга функций, определенных в том же модуле, - это меньшая его часть: другим следствием является то, что если у вас есть сращивание на верхнем уровне, все после него в модуле будет вне видимости чего-либо перед ним. Другие языки с этим свойством (C, C++) делают его работоспособным, позволяя вам пересылать объявления, но Haskell этого не делает. Если вам нужны циклические ссылки между объявлениями сплайсинга или их зависимостями и иждивенцами, вы обычно просто ввернуты.
Я столкнулся с вопросом циклических определений TH будучи невозможно до ... Это очень раздражает. Существует решение, но оно уродливо - обертывание вещей, связанных с циклической зависимостью в выражении TH, которое объединяет все сгенерированные объявления. Один из этих генераторов объявлений может быть просто квазициклером, который принимает код Haskell.
- Это беспринципный. Я имею в виду, что большую часть времени, когда вы выражаете абстракцию, для этой абстракции есть какой-то принцип или понятие. Для многих абстракций принцип, лежащий в их основе, может быть выражен в их типах. Когда вы определяете класс типа, вы часто можете формулировать законы, которые должны подчиняться, и клиенты могут принять их. Если вы используете функцию [new generics feature] GHC [3], чтобы абстрагировать форму объявления экземпляра по любому типу данных (в пределах границ), вы можете сказать «для типов сумм, он работает, как это, для типов продуктов, он работает так ». Но Template Haskell - это просто немые макросы. Это не абстракция на уровне идей, а абстракция на уровне АСТ, которая лучше, но лишь скромно, чем абстракция на уровне обычного текста.
Это только беспринципный, если вы беспринципных вещи с ним. Единственное отличие заключается в том, что при компиляторе реализованы механизмы абстракции, у вас больше уверенности в том, что абстракция не является протекающей. Возможно, демократизация языкового дизайна звучит немного страшно! Создатели библиотек TH должны хорошо документировать и четко определять смысл и результаты инструментов, которые они предоставляют. Хорошим примером принципиального TH является производный пакет: http://hackage.haskell.org/package/derive - он использует DSL, такой, что пример многих дериваций/указывает/фактический вывод.
- Это связывает вас с GHC. Теоретически другой компилятор мог бы его реализовать, но на практике я сомневаюсь, что это когда-нибудь произойдет. (Это в отличии от различных систем типа расширений, которые, хотя они могут быть реализованы только GHC на данный момент, я мог бы легко себе представить, принимаемые другими компиляторами вниз по дороге и в конце концов стандартизированы.)
Это довольно хороший момент - TH API довольно большой и неуклюжий. Повторное внедрение кажется, что это может быть жестким. Тем не менее, существует всего лишь несколько способов разрезать проблему представления Haskell AST. Я предполагаю, что копирование TH ADT и запись конвертера во внутреннее представление AST обеспечили бы вам много пути. Это было бы эквивалентно (не несущественному) усилию создания haskell-src-meta. Его также можно было бы просто переделать, напечатав TH AST и используя внутренний синтаксический анализатор компилятора.
Хотя я мог ошибаться, я не вижу, чтобы TH был настолько сложным из расширения компилятора, с точки зрения реализации.Это на самом деле одно из преимуществ «поддержания его простоты» и не имеющего фундаментального уровня как теоретически привлекательной, статически проверяемой системы шаблонов.
- API нестабилен. Когда новые функции языка добавляются в GHC, а пакет template-haskell обновляется для их поддержки, это часто включает в себя обратные несовместимые изменения типов данных TH. Если вы хотите, чтобы ваш код TH был совместим с более чем одной версией GHC, вам нужно быть очень осторожным и, возможно, использовать
CPP
.
Это также хороший момент, но несколько драматизированный. Несмотря на то, что в последнее время были добавлены API, они не подвергались экстенсивно обрыву. Кроме того, я думаю, что с вышеизложенным выше, упомянутым мной ранее, API, который действительно должен использоваться, может быть значительно сокращен. Если никакая конструкция/соответствие не нуждается в различных функциях и вместо этого выражаются как литералы, тогда большая часть API исчезает. Более того, код, который вы пишете, будет легче переноситься в представления AST для языков, подобных Haskell.
Таким образом, я считаю, что TH является мощным, полузапускаемым инструментом. Меньшая ненависть может привести к более оживленной экосистеме библиотек, поощряя внедрение более языковых прототипов. Было замечено, что TH является мощным инструментом, который может позволить вам/делать/почти что угодно. Анархия! По моему мнению, эта сила может позволить вам преодолеть большинство своих ограничений и построить системы, способные к совершенно принципиальным подходам метапрограммирования. Стоит использовать уродливые хаки для имитации «правильной» реализации, так как таким образом дизайн «правильной» реализации постепенно станет ясным.
В моей личной идеальной версии нирваны большая часть языка фактически выйдет из компилятора в библиотеки этого сорта. Тот факт, что функции реализованы в виде библиотек, не сильно влияет на их способность к достоверному абстрактному.
Каков типичный ответ Haskell на шаблонный код? Абстракция. Какие наши любимые абстракции? Функции и модели.
Typeclasses позволяет определить набор методов, которые затем могут использоваться во всех функциях, общих для этого класса. Однако, кроме этого, единственный способ, которым классы помогают избежать шаблона, - это предлагать «определения по умолчанию». Теперь вот пример беспринципной функции!
Минимальные наборы сложения не подлежат декларированию/компилятору. Это может привести к непреднамеренным определениям, которые дают дно из-за взаимной рекурсии.
Несмотря на большое удобство и мощность, это может привести к тому, что вы не можете указать значения по умолчанию для суперкласса из-за сиротских экземпляров http://lukepalmer.wordpress.com/2009/01/25/a-world-without-orphans/ Это позволит нам исправить числовую иерархию изящно!
Переход на TH-подобные возможности для значений по умолчанию метода привел к http://www.haskell.org/haskellwiki/GHC.Generics. Хотя это классный материал, мой единственный опыт отладки кода с использованием этих дженериков был практически невозможным из-за размера индуцированного типа и ADT, такого сложного, как AST. https://github.com/mgsloan/th-extra/commit/d7784d95d396eb3abdb409a24360beb03731c88c
Другими словами, это продолжалось после функций, предоставляемых TH, но ему пришлось поднять весь домен языка, язык конструкции, в системное представление типа. Хотя я вижу, что это хорошо работает для вашей общей проблемы, для сложных, кажется, склонно уступать кучу символов, гораздо более ужасающих, чем TH-хакерство.
TH дает вам вычисление выходного кода на уровне значений, тогда как generics заставляет вас поднять часть соответствия шаблону/рекурсии кода в систему типов. Хотя это и ограничивает пользователя несколькими довольно полезными способами, я не думаю, что это стоит того.
Я думаю, что отказ от TH и сюсюкать-как метапрограммированием привел к предпочтению к вещам, как метод дефолт вместо более гибкого, макро-расширение, как декларации экземпляров. Дисциплина избегать вещей, которые могут привести к непредсказуемым результатам, разумна, однако мы не должны игнорировать, что система Haskell, способная к типу, позволяет более надежное метапрограммирование, чем во многих других средах (путем проверки сгенерированного кода).
Проголосовало за Close: принадлежит программистам.stackexchange.com - Вопросы и ответы для профессиональных программистов, заинтересованных в концептуальных вопросах разработки программного обеспечения –
Я не согласен с голосованием на переезд; Я задаю этот вопрос в том же духе, что и я спросил: «Что плохого в ленивом I/O?» (Http://stackoverflow.com/questions/5892653/whats-so-bad-about-lazy-io), и я ожидайте увидеть ответы одинаково. Я готов переформулировать вопрос, если это поможет. –
@ErikPhilips Почему бы вам не позволить людям, которые часто посещают этот тег, решить, принадлежит ли это здесь? Кажется, что ваше единственное взаимодействие с сообществом Haskell заключается в том, чтобы задать свои вопросы. –