Прямо сейчас у меня есть следующий фрагмент кода в моем проекте:
embedNarration :: String -> Q Exp
embedNarration file =
let text = unsafePerformIO $ readFile file
parsedMaybe = parseNarration text
succ x = case x of
Left x -> throw $ ErrorCall x
Right x' -> x'
parsed = succ parsedMaybe
res = do parser <- [|((fromRight undefined) . parseNarration)|]
d <- return $ seq parsed text
return $ AppE parser $! LitE $! StringL d
in res
Который подстроен жюри из исходного кода модуля Data.FileEmbed.Целью кода является создание Повествования (которое представляет собой структуру данных, определенную в коде) из файла ресурсов.
Прямо сейчас эта довольно уродливая часть, которую я не совсем понимаю, пытается проанализировать файл ресурсов;выдает ошибку времени компиляции, если анализ не выполнен;или, если анализ успешен, встраивает следующий фрагмент в исходный код:
((fromRight undefined) . parseNarration $ "THE ENTIRE RESOURCE FILE")
Где parseNarration - функция :: String -> Either String Narration
Проблема здесь заключается в двойном синтаксическом анализе - ресурсефайл анализируется один раз во время компиляции, чтобы убедиться, что он действителен, а затем второй раз во время выполнения из строкового литерала.В идеале, вместо строкового литерала и вызова синтаксического анализатора я хочу, чтобы TemplateHaskell напрямую заменял повествование, чтобы синтаксический анализатор существовал только во время компиляции.Но я понятия не имею, как это сделать.Поверхностные руководства к TemplateHaskell и попытки подправить код дальше не увенчались успехом.Возможно ли это сделать?Если да, то как?