[英]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.