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