在不使用列表的情况下嵌入长字符串

时间:2014-08-05 21:34:49

标签: haskell template-haskell

对于几个项目,我需要将长字符串嵌入到Haskell源代码中。

显而易见的方法是unlines一系列行。但是,阅读和维护这个很麻烦。

cCode :: String
cCode = unlines [
          "int main(int argc*, char** argv)",
          "  doStuff();",
          "}"]

有没有办法可以在没有任何开销的情况下嵌入字符串(如上图所示的列表)甚至文件? TemplateHaskell / Quasi-quotation是走这里的方式吗?

注意:此问题已在Q& A表单中得到解答。因此,它没有显示任何研究工作。

2 个答案:

答案 0 :(得分:5)

可以使用QuisQuotation描述in this blogpost written by me

第1步:创建一个模块(我们将其称为StringEmbed.hs,其中包含所需的功能

module StringEmbed(embedStr, embedStrFile) where

import Language.Haskell.TH
import Language.Haskell.TH.Quote

embedStr :: QuasiQuoter 
embedStr = QuasiQuoter { quoteExp = stringE,
                    quotePat = undefined,
                    quoteDec = undefined,
                    quoteType = undefined }

embedStrFile :: QuasiQuoter
embedStrFile = quoteFile embedStr

请注意,由于TH的特殊性, 可能只是将这些功能复制到您使用它们的模块中。

步骤2a:在您的模块中,嵌入字符串:

{-# LANGUAGE QuasiQuotes #-}

import StringEmbed

cCode :: String
cCode = [embedStr|
int main(int argc, char** argv) {
    doStuff();
}
|]

请注意,您只需添加QuasiQuotes LANGUAGE pragma。此技术不需要TemplateHaskell

因为QuasiQuotes是使用|]分隔的,所以你不能在准引用字符串中的任何地方使用该字符序列。

步骤2b:您可以轻松嵌入文件。我们假设文件code.c包含您要嵌入的字符串。

{-# LANGUAGE QuasiQuotes #-}

import StringEmbed

cFooter :: String
cFooter = [embedStrFile|code.c|]

或者您可以使用众多haskell库中的一个而不是StringEmbed.hs,例如heredoc(感谢Ørjan Johansen提示!)

{-# LANGUAGE QuasiQuotes #-}
import Text.Heredoc


cCode :: String
cCode = [here|
int main(int argc, char** argv) {
    doStuff();
}
|]

答案 1 :(得分:3)

您可以使用带有间隙的多行字符串。它可能不如quasiquoters那么顺利,但它是标准的Haskell。

cCode :: String
cCode = "\
      \int main(int argc*, char** argv)\n\
      \  doStuff();\n\
      \}\n\
      \"