Как явно назвать квазиквотер для синтаксиса haskell?

Я строю eDSL поверх HaTeX. Проблема, с которой я сталкиваюсь, заключается в том, что я хочу отобразить выражения Haskell в своем документе LaTeX и использовать то же выражение Haskell, чтобы помочь сгенерировать документ.

Очевидный ответ - скопировать и вставить выражение, чтобы оно отображалось как в кавычках, так и вживую. Я хочу избежать этого, потому что выражение может быть изменено.

Я представляю себе квазиквотер, который объединяет его содержимое в том виде, в каком он есть, и выдает строку, представляющую его.

Например, вот что я хотел бы ввести:

document = do
    title "this is an example document"
    paragraph "This is normal text. We will now show the Haskell code that generates a table"
    [quoted| makeTable ["heading1","heading2"] ["cell1","cell2"] |]

и я хотел бы, чтобы квази-цитата расширилась до:

document = do
    title "this is an example document"
    paragraph "This is normal text. We will now show the Haskell code that generates a table"
    makeTable ["heading1","heading2"] ["cell1","cell2"]
    listing Haskell "makeTable [\"heading1\",\"heading2\"] [\"cell1\",\"cell2\"]"

Для этого мне нужно написать QuasiQuoter:

quoted :: QuasiQuoter
quoted = QuasiQuoter
     { quoteExp = \str -> [e| $(_ str) >> listing Haskell $(lift str) |] }

Я не уверен, что заменить отверстие в $(_ str), Мне нужно заменить его квази-квотером выражения Haskell, но я не знаю, как его назвать. Если e было e :: QuasiQuoter Я мог бы заполнить дыру $(quoteExp e str) но это, к сожалению, не работает. Чем мне его заполнить?

1 ответ

Решение

Краткий ответ: нет простого пути. Этот вопрос до сих пор остался без ответа по причине. String -> Q Exp для Хаскелла это сложно. Лучший способ, вероятно, через haskell-src-meta который предоставляет парсеры, которые возвращают шаблон Haskell AST. В частности Language.Haskell.Meta.Parseмодуль дает нам parseExp :: String -> Either String Exp,

import Language.Haskell.Meta.Parse (parseExp)

quoted :: QuasiQuoter
quoted = QuasiQuoter
     { quoteExp = \str ->
         case parseExp str of
           Left msg -> fail "Could not parse expression."
           Right exp -> [e| $(pure exp) >> listing Haskell $(liftString str) |] }
Другие вопросы по тегам