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是否保证在编译时连接字符串字面量?
如果我有
"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"
...
并查看字符串是否已经在核心中间语言中合并。
编辑:为了强调我对其他答案的赞同,仅仅因为这个特定的程序在合并字符串时出现了核心转储,并不意味着编译器会对所有字符串都执行此操作。符合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中检查,合并的字符串是在编译时生成的。