Подтвердить что ты не робот

Шаблон Haskell: Есть ли функция (или специальный синтаксис), которая анализирует строку и возвращает Q Exp?

Я пытаюсь изучить немного шаблона Haskell и Quasi Quotation, и я ищу функцию, которая принимает String и анализирует ее на Q Exp, поэтому тип:

String -> Q Exp

Пробовал поиск hoogle, но результаты, которые я видел, связаны с подъемом строковых литералов до Q Exp, и ближайший я нашел Language.Haskell.TH.dyn, который делает то, что я хочу, но только для одной переменной.

Есть ли другие варианты? Например. специальный синтаксис? Я просто разбираюсь в [||] и $(), так что, возможно, есть что-то для этой цели?

Пример того, как я предполагаю, что это сработает:

runQ (parse "(1+)") == InfixE (Just (LitE (IntegerL 1))) (VarE GHC.Num.+) Nothing

Кроме того, я знаю об этом

runQ [| (1+) |] == InfixE (Just (LitE (IntegerL 1))) (VarE GHC.Num.+) Nothing

но это не работает с переменными строками, потому что - понятно - строка внутри берется как литерал.

runQ [| "(1+)" |] == LitE (StringL "(1+)")

Изменить (2015-07-25): Я начал использовать haskell-src-meta, и, похоже, он работает до сих пор. Однако для cabal install (около 10 минут на моей машине) требуется довольно много времени. Какой позор, мой пакет на самом деле довольно мал, и я хотел бы, если бы установка была быстрой. Кто-нибудь знает о решении, которое имеет меньшие зависимости?

4b9b3361

Ответ 1

Как все уже сказали haskell-src-meta предоставляет

parsePat :: String -> Either String Pat
parseExp :: String -> Either String Exp
parseType :: String -> Either String Type
parseDecs :: String -> Either String [Dec]

где Pat, Exp, Type и Dec такие же, как от Language.Haskell.TH.Syntax.


Почему GHC не выставляет собственный парсер?

Это так. Fire GHCi с ghci -package ghc (ghc- скрытый пакет по умолчанию), и вы можете импортировать Parser. Он имеет функции для синтаксического анализа String в предварительные АСТ (декларации данных которых находятся в HsSyn) для шаблонов, выражений, типов и деклараций.

ОК, тогда почему не существует библиотеки, которая использует этот синтаксический анализатор, и преобразует свой вывод в AST из template-haskell (тот, который находится в Language.Haskell.TH.Syntax)?

Заглядывая в HsSyn, очевидно, что AST не совсем то же самое, что в Language.Haskell.TH.Syntax. Откройте оба HsExpr и Exp и бок о бок вы увидите, что последний заполнен такими типами, как PostTc id <some-other-type> и PostRn id <some-other-type>. Поскольку AST передается от анализатора к переименованному устройству проверки типов, эти биты и кусочки медленно заполняются. Например, мы даже не знаем ограничений операторов до тех пор, пока не получим проверку типов!

Чтобы выполнить нужные функции, нам нужно будет запускать гораздо больше, чем просто синтаксический анализатор (по крайней мере, переименовать и проверить тип, возможно, больше). Представьте себе, что: каждый раз, когда вы хотите разобрать даже небольшое выражение, например "1 + 2", вам все равно придется набирать контрольный кучу импорта. Даже тогда преобразование обратно в Language.Haskell.TH.Syntax не было бы прогулкой в ​​парке: GHC имеет множество особенностей, таких как собственные специальные глобальный способ хранения имен и идентификаторов.

Хммм... но что делает GHC с квазициклами?

Это крутая часть! В отличие от Exp, HsExpr имеет HsSplice для представления сращений. Посмотрите типы для первых двух конструкторов:

HsTypedSplice :: id -> LHsExpr id -> HsSplice id.   -- things like [|| 1 + 2 ||]
HsUntypedSplice :: id -> LHsExpr id -> HsSplice id  -- things like [| 1 + 2 |]

Обратите внимание, что они не сохраняют String, они уже хранят AST! Сочетания обрабатываются одновременно с остальной частью АСТ. И точно так же, как и остальные АСТ, сращивания будут передаваться вместе с переименователем, контролером типа и т.д., Где пропущенная информация будет заполнена.

Так что в принципе невозможно использовать парсер GHC

Наверное, нет. Но вывести его из остальной части GHC может быть довольно сложно. Если использовать парсер GHC, мы должны также запустить средство проверки типов и переименовать, может быть более элегантным и простым просто использовать автономный синтаксический анализатор, такой как haskell-src-exts (от которого зависит haskell-src-meta), который может сделать все за один проход (например, исправления - это одна из вещей, которые вы должны заранее дать этому парсеру).