繁体   English   中英

Haskell在编译时是否连接了字符串文字?

[英]Does Haskell concatenate String literals at compile time?

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

如果我有

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

编译器会将其视为

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

如果可能的话,我想保持我的源行长度不超过80个字符,但我不想引入运行时效率低下。

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"

...

并看到该字符串已在Core中间语言中合并。


编辑:为了强调我与其他答案的一致,仅仅因为这个特定的程序有一个带有合并字符串的核心转储,并不能保证编译器会为所有字符串执行此操作。 遵守Haskell规范并不意味着事情如何编译。

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

没有。

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

另外,说在编译期间应该做什么会给解释器带来麻烦,例如Hugs。

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

Haskell 2010仅在错误的背景下讨论编译时间。 (例如,类型错误保证是编译时。)

使用间隙 - 反斜杠之间的一个或多个空白字符序列:

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

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

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

我没有这个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,即在编译时生成连接字符串。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM