Существует ли шаблон haskell для цитирования?
Я играю с Template Haskell. Я хочу создать квазициклер, который позволяет мне создавать инициализаторы по умолчанию для записей, т.е. Что-то вроде
[record| data Config = { shouldDoX = True; featureY :: Integer, optionZ = Nothing } |]
должна создать функцию
defaultConfig = Config { shouldDoX = True, optionZ = Nothing }
В основном это тот же синтаксис, что и объявления данных, расширенные по умолчанию. Теперь record
является обычным QuasiQuoter, однако есть выражения и типы, внутри которых я не хочу анализировать себя. В идеале мне нужно было бы разделить блок внутри фигурных скобок на утверждения и искать =
и ::
.
Итак, я ищу функцию, которая фактически делает то же самое, что и с [e| ...|]
или [t| ...|]
. Я искал Hoogle для функции String -> ExpQ
или String -> Q Exp
, но ничего не нашел.
Если я не понял, что я ищу: Я знаю о QuasiQuoters. Как я уже говорил, record
является QuasiQuoter. Теперь строка, которая передается моему квазициктору, содержит выражения (например, Node 7 (Node 8 Nil Nil) Nil
) и типы (например, True
или Maybe (Either A B)
)). Я мог бы разобрать их сам, но я надеюсь, что есть функция, которая сделает это для меня, как если бы я передал строку в цитату вроде [e|...|]
.
Итак: Я ищу функцию, которую я могу выразить выражением как String или Type as String, и который возвращает соответствующий объект Exp
или Type
. Я считаю, что он должен жить в монаде Q, так как он должен оценивать выражение или тип на основе контекста (так же, как и цитаты).
functionOfMyDreams "Node 7 (Node 8 Nil Nil) Nil" :: Q Exp
Ответы
Ответ 1
Я думаю, что функции
parseExp :: String -> Either String Exp
parseType :: String -> Either String Type
из пакета haskell-src-meta
- это то, что вы хотите.
http://hackage.haskell.org/package/haskell-src-meta-0.6.0.4/docs/Language-Haskell-Meta-Parse-Careful.html
Вот самодостаточный пример квазивокатора, который может аннотировать и вставлять выражения Хаскелла с помощью haskell-src-meta
.
Ответ 2
У вас есть правильная идея, но это будет функция типа String -> Q [Dec]
Чтобы создать квазикватер, вам нужно создать значение типа QuasiQuoter, которое имеет четыре функции типа String -> Q Blah
, где Blah является Шаблоном Тип Haskell, с которым вы соединяетесь.
В вашем случае вам нужно всего лишь определить кадр объявления.
quoteRecord :: String -> Q [Dec]
quoteRecord = ...
record :: QuasiQuoter
record = QuasiQuoter (error "record is not a expression quoter")
(error "record is not a pattern quoter")
(error "record is not a type quoter")
quoteRecord
Затем вы можете использовать свой квазикватер записи в другом файле
[record| ... |]
Существует хорошая прогулка по Haskell wiki
Вы также можете проверить BNFC-meta, который будет генерировать квазикватер из грамматики.