2014-12-08 3 views
8

Я хочу написать предложение в Haskell. Аргумент name должен быть передан в функцию gen для генерации объявления.QuasiQuote с аргументами

quote :: String -> QuasiQuoter 
quote name = QuasiQuoter { 
     quoteExp = undefined, 
     quotePat = undefined, 
     quoteType = undefined, 
     quoteDec = \jsonStr -> gen name (getValue str) 
    } 

Тем не менее, кажется, что я не могу использовать эту цитату, как этот

[quote "Hello"| from x to y |] 

Поскольку Haskell не позволяет цитировать заявления и цитаты, чтобы быть в том же файле, который раздражает, что я могу сделать, чтобы передать аргумент из стороны в цитату?

ответ

6

У вас есть два варианта:

  1. Переключитесь на использование сращивания $(...),
  2. Кодируйте параметр квази-Quoter во входной строке.

С синтаксисом сращивания ваш пример будет выглядеть так:

quote :: String -> String -> Q [Dec] 
quote name jsonStr = gen name (getValue jsonStr) 

и вызов выглядит так: $(quote "Hello" "from x to y")

Чтобы продемонстрировать вариант 2, вот простой Цитатник, которая окружает символьной строки с знак:

import Language.Haskell.TH (litE, stringL) 
import Language.Haskell.TH.Quote 

surround :: QuasiQuoter 
surround = QuasiQuoter 
    { quoteExp = litE . stringL . (\(c:s) -> [c] ++ s ++ [c]) 
    , quotePat = undefined 
    , quoteType = undefined 
    , quoteDec = undefined 
    } 

-- in another file: 
main = print [surround|_some text|] -- prints "_some text_" 

Первый символ входной строки интерпретируется как brac ket для использования. Фактически мы передали параметр Char функции типа Char -> QuasiQuoter.

Для более сложных параметров или нескольких параметров вам необходимо будет создать собственный синтаксис и парсер для их декодирования.

Update: Вот несколько более сложный пример, где призывание [foo| var xyz|] лечит var как имя переменной и xyz как буквенная строка: обновление

-- [foo| var xyz|] is translated to: var ++ "xyz" 

foo :: QuasiQuoter 
foo = QuasiQuoter 
    { quoteExp = go 
    , quotePat = undefined 
    , quoteType = undefined 
    , quoteDec = undefined 
    } 
    where go str = infixE (Just $ varE (mkName var)) 
         (varE $ mkName "++") 
         (Just $ litE (stringL arg1)) 
      where (var:arg1:_) = words str 
+0

Ответ добавить опцию сплайсинга. – ErikR

 Смежные вопросы

  • Нет связанных вопросов^_^