Haskell是否在编译时连接字符串文本?
Haskell 2010是否保证在编译时连接字符串文本 如果我有Haskell是否在编译时连接字符串文本?,haskell,concatenation,string-literals,Haskell,Concatenation,String Literals,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"
...
[1/1]编译Main(Test.hs,Test.o)
=====================================整齐的核心====================
Tidy Core的结果大小={terms:19,type:23,强制:9}
main2::[Char]
[GblId,
Unf=Unf{Src=,TopLvl=True,Arity=0,Value=False,
ConLike=False,WorkFree=False,Expandable=False,
指导=如果参数[]60 0}]
main2=解压字符串#“你好,世界”
...
并查看字符串已合并到核心中间语言中
编辑:为了强调我对其他答案的同意,仅仅因为这个特定的程序有一个包含合并字符串的核心转储,并不保证编译器会对所有字符串执行此操作。遵循Haskell规范并不意味着什么东西是如何编译的 Haskell 2010是否保证在编译时连接字符串文本 没有 运行时效率远远超出了Haskell 2010的范围。我们不想仅仅因为实验性实现速度慢就禁止它们 此外,说出编译时应该做什么会给口译员带来麻烦,比如拥抱 最后,给实现者一些自由是有用的。也许在某些奇怪的情况下,不预计算字符串实际上会更快
Haskell 2010只在错误上下文中讨论编译时。(例如,类型错误保证在编译时发生。)我不认为haskell保证了这一点。可能会有像
ghc
这样的编译器来执行这种优化,但是没有标准来保存这种优化。因此,在未来的版本中,这种优化可能不会发生
如果您真的想保证模板Haskell是在编译时完成的,为什么不使用它呢。以下示例在ghc上进行了测试,但我认为您也可以在其他编译器上使用它:
在模块文件中,可以有如下代码
module Concat where
import Language.Haskell.TH
(<++>) :: String -> String -> ExpQ
(<++>) x y = stringE (x ++ y)
模块Concat在哪里
导入语言.Haskell.TH
()::字符串->字符串->表达式
()x y=弦(x++y)
然后在实际执行编译时连接所需的文件中
{-# LANGUAGE TemplateHaskell #-}
import Concat
f = $("This is a very long string" <++>
"which spans over several lines")
{-#语言模板haskell}
进口海螺
f=$(“这是一个很长的字符串”
“跨越多条线路的电缆”)
您甚至可以使用
-ddump拼接
在ghc中检查连接的字符串是否在编译时生成。在反斜杠之间使用一个或多个空格字符的间隔:
"This is a \
\very long String that \
\spans several lines"
零宽度等效值为\&
,用于从数字字符中分离数字转义:
"\123\&45" == "{45"
"\12345" == "〹"
还有使用拼接而不是内联运算符的。@tel谢谢。这看起来更好用。小心使用“核心转储”打印中间核心代码:-)我可能传达了一种人工感觉,即窥视核心和了解事物的行为是多么容易。。。但是我经常发现这没那么难。刚开始就让人畏缩。