Domanda

Does Haskell 2010 guarantee to concatenate String literals at compile time?

If I have

"This is a " ++
"very long String that " ++
"spans several lines"

does the compiler treat it as

"This is a very long String that spans several lines"

I want to keep my source lines less than 80 characters long if possible, but I don't want to introduce run-time inefficiency.

È stato utile?

Soluzione 3

Use a gap—a sequence of one or more whitespace characters between backslashes:

"This is a \
\very long String that \
\spans several lines"

The zero-width equivalent is \&, useful for separating numeric escapes from digit characters:

"\123\&45" == "{45"
"\12345" == "〹"

Altri suggerimenti

Does Haskell 2010 guarantee to concatenate String literals at compile time?

No.

Run-time efficiency is far away from the scope of Haskell2010. We don't want to ban experimental implementations just because they are slow.

Also, saying what should be done during the compile time would cause troubles for interpreters, such as Hugs.

Finally, it is useful to give some freedom to implementors. Perhaps under some strange circumstances it would be actually faster not to precompute the string?

Haskell 2010 talks about compile time only in the context of errors. (E.g. type errors are guaranteed to be compile-time.)

Haskell 2010 guarantees that it's denotationally equivalent to the merged string, but has nothing to say about how it should be compiled. It's easy enough to check with the ghc-core tool, though.

-- Test.hs
main = putStrLn $ "Hello " ++ "world"

and when we run 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"

...

and see that the string has been merged in the Core intermediate language.


Edit: To emphasize my agreement with other answers, just because this particular program has a core dump with the merged string does not guarantee that the compiler will do it for all strings. Being compliant with the Haskell spec doesn't imply much at all about how things get compiled.

I don't this haskell guarantees that. There might be come compilers like ghc performing this optimisation but there is no standard preserving this. So it might happen that in a future version this optimisation might not occur.

Why don't you use Template Haskell if you really want to guarantee that it is done at compile time. Following example is tested on ghc but I think you can make it work on other compilers too:

In a module file you can have a code like this

module Concat where
import Language.Haskell.TH

(<++>) :: String -> String -> ExpQ
(<++>) x y = stringE (x ++ y)

Then in the file which you require to actually do the compile time concatenation

{-# LANGUAGE TemplateHaskell #-}
import Concat

f = $("This is a very long string" <++>
      "which spans over several lines")

You can even check in ghc by using -ddump-splices that the concatenated string is generated at compile time.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top