Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell是否在编译时连接字符串文本?_Haskell_Concatenation_String Literals - Fatal编程技术网

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

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保证它在字面上等同于合并字符串,但没有说明应该如何编译它。不

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谢谢。这看起来更好用。小心使用“核心转储”打印中间核心代码:-)我可能传达了一种人工感觉,即窥视核心和了解事物的行为是多么容易。。。但是我经常发现这没那么难。刚开始就让人畏缩。