Haskell 2010是否保证在编译时连接字符串文字?
如果我有
"This is a " ++
"very long String that " ++
"spans several lines"
编译器是否将其视为
"This is a very long String that spans several lines"
如果可能的话,我想保持源行不超过80个字符,但我不想引入运行时效率低下。
答案 0 :(得分:19)
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规范并不意味着如何编译事物。
答案 1 :(得分:19)
Haskell 2010是否保证在编译时连接字符串文字?
没有
运行时效率远离Haskell2010的范围。我们不想仅仅因为它们很慢而禁止实验性实施。
另外,说在编译期间应该做些什么会给解释者带来麻烦,例如Hugs。
最后,为实现者提供一些自由是很有用的。也许在某些奇怪的情况下,预先计算字符串实际上会更快吗?
Haskell 2010仅在错误的上下文中讨论编译时间。 (例如,类型错误保证是编译时。)
答案 2 :(得分:16)
使用间隙 - 反斜杠之间的一个或多个空白字符序列:
"This is a \
\very long String that \
\spans several lines"
零宽度等效值为\&
,对于将数字转义符与数字字符分开非常有用:
"\123\&45" == "{45"
"\12345" == "〹"
答案 3 :(得分: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是否在编译时生成了连接字符串。