Haskell 是否在编译时连接字符串字面量?

21

Haskell 2010是否保证在编译时连接字符串字面量?

如果我有

"This is a " ++
"very long String that " ++
"spans several lines"

编译器是否将其视为

"This is a very long String that spans several lines"

如果可能的话,我希望保持源代码每行不超过80个字符,但又不想引入运行时的低效。

4个回答

20

Haskell 2010保证它在表示上等同于合并的字符串,但对于如何编译它没有什么可说的。不过,使用ghc-core工具很容易进行检查。

-- Test.hs
main = putStrLn $ "Hello " ++ "world"

当我们运行 ghc-core Test.hs

[1 of 1] Compiling Main             ( Test.hs, Test.o )

==================== Tidy Core ====================
Result size of Tidy Core = {terms: 19, types: 23, coercions: 9}

main2 :: [Char]
[GblId,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Arity=0, Value=False,
         ConLike=False, WorkFree=False, Expandable=False,
         Guidance=IF_ARGS [] 60 0}]
main2 = unpackCString# "Hello world"

...

并查看字符串是否已经在核心中间语言中合并。


编辑:为了强调我对其他答案的赞同,仅仅因为这个特定的程序在合并字符串时出现了核心转储,并不意味着编译器会对所有字符串都执行此操作。符合Haskell规范并不能说明有关编译方式的信息。


小心使用“核心转储”来打印中间核心代码 :-) - David
我可能传达了一种人工的感觉,让人觉得窥视核心并了解事物的行为有多容易... 但是!我经常发现这并不那么困难。只是起初有些令人望而却步。 - J. Abrahamson

19

Haskell 2010能否保证在编译时连接字符串字面量?

不行。

运行时间效率远离Haskell2010的范围。我们不想仅因为它们很慢就禁止实验性实现。

此外,在编译时说应该做什么会给解释器(如Hugs)带来麻烦。

最后,给实现者一些自由是有用的。也许在某些奇怪的情况下,不预先计算字符串实际上会更快?

Haskell 2010只在错误的上下文中谈到编译时。(例如,类型错误保证是编译时的。)


16

使用空格间隔——在反斜杠之间放置一个或多个空格字符的序列:

"This is a \
\very long String that \
\spans several lines"

零宽度等价于\&,用于将数字转义字符与数字字符分开:

"\123\&45" == "{45"
"\12345" == "〹"

4

我认为 Haskell 并不保证这一点。可能有些编译器(如 ghc)会执行这种优化,但没有标准来保留它。因此,在未来的版本中可能不会发生这种优化。

如果你真的想保证它在编译时完成,为什么不使用 Template Haskell 呢?以下示例已在 ghc 上测试过,但我认为你也可以在其他编译器上使其工作:

在模块文件中,你可以像这样编写代码:

module Concat where
import Language.Haskell.TH

(<++>) :: String -> String -> ExpQ
(<++>) x y = stringE (x ++ y)

然后在需要进行编译时串联的文件中,你需要实际执行这个过程。

{-# LANGUAGE TemplateHaskell #-}
import Concat

f = $("This is a very long string" <++>
      "which spans over several lines")

你甚至可以使用-ddump-splices在GHC中检查,合并的字符串是在编译时生成的。


5
这里还有一个“穷人版”的Here Document(文本块),使用的是拼接语法而非行内运算符。详情请见链接:http://www.haskell.org/haskellwiki/Poor_man's_here_document。 - J. Abrahamson
@tel 谢谢。看起来更好用了。 - Satvik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接