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

Uli*_*ler 4 haskell template-haskell

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

显而易见的方法是unlines使用行列表.但是,阅读和维护这一过程非常麻烦.

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

有没有什么方法可以嵌入字符串而没有任何开销(如上面显示的列表)甚至文件?TemplateHaskell/Quasi-quotation是走这里的方式吗?

注意:此问题以问答形式回答.因此,它没有显示任何研究工作.

Uli*_*ler 5

可以使用QuasiQuotation,如我在此博文中所描述的那样.

第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
Run Code Online (Sandbox Code Playgroud)

请注意,由于TH的特殊性,无法将这些功能复制到您使用它们的模块中.

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

{-# LANGUAGE QuasiQuotes #-}

import StringEmbed

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

请注意,您只需添加QuasiQuotes LANGUAGE编译指示.TemplateHaskell这种技术不是必需的.

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

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

{-# LANGUAGE QuasiQuotes #-}

import StringEmbed

cFooter :: String
cFooter = [embedStrFile|code.c|]
Run Code Online (Sandbox Code Playgroud)

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

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


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