posicion - ¿Haskell concatena literales de cadenas en tiempo de compilación?
ordenar lista haskell (4)
¿Haskell 2010 garantiza concatenar literales de cadenas en tiempo de compilación?
No.
La eficiencia en tiempo de ejecución está muy lejos del alcance de Haskell2010. No queremos prohibir las implementaciones experimentales solo porque son lentas.
Además, decir qué se debe hacer durante el tiempo de compilación podría causar problemas a los intérpretes, como los abrazos.
Finalmente, es útil dar algo de libertad a los implementadores. ¿Quizás bajo algunas extrañas circunstancias sería más rápido no calcular previamente la cadena?
Haskell 2010 habla sobre el tiempo de compilación solo en el contexto de errores. (Por ejemplo, los errores de tipo se garantizan en tiempo de compilación).
¿Haskell 2010 garantiza concatenar literales de cadenas en tiempo de compilación?
Si tengo
"This is a " ++
"very long String that " ++
"spans several lines"
¿El compilador lo trata como
"This is a very long String that spans several lines"
Quiero mantener mis líneas de origen con menos de 80 caracteres si es posible, pero no quiero introducir la ineficiencia del tiempo de ejecución.
Haskell 2010 garantiza que es denotativamente equivalente a la cadena fusionada, pero no tiene nada que decir acerca de cómo debe compilarse. Sin embargo, es bastante fácil verificarlo con la herramienta ghc-core
.
-- Test.hs
main = putStrLn $ "Hello " ++ "world"
y cuando ejecutamos 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"
...
y ver que la cadena se ha fusionado en el lenguaje intermedio principal.
Edición: para enfatizar mi acuerdo con otras respuestas, solo porque este programa en particular tiene un volcado central con la cadena fusionada no garantiza que el compilador lo haga para todas las cadenas. Ser compatible con la especificación de Haskell no implica mucho en absoluto acerca de cómo se compilan las cosas.
Use un espacio, una secuencia de uno o más caracteres de espacio en blanco entre barras invertidas:
"This is a /
/very long String that /
/spans several lines"
El equivalente de ancho cero es /&
, útil para separar escapes numéricos de caracteres de dígitos:
"/123/&45" == "{45"
"/12345" == "〹"
Yo no este haskell garantiza eso. Puede haber compiladores de ghc
como ghc
realizando esta optimización, pero no hay un estándar que lo conserve. Por lo tanto, puede suceder que en una versión futura esta optimización no ocurra.
¿Por qué no usa Template Haskell si realmente quiere garantizar que se haga en tiempo de compilación? El siguiente ejemplo se prueba en ghc, pero creo que también puede hacerlo funcionar en otros compiladores:
En un archivo de módulo puedes tener un código como este
module Concat where
import Language.Haskell.TH
(<++>) :: String -> String -> ExpQ
(<++>) x y = stringE (x ++ y)
Luego, en el archivo que necesita para realizar la concatenación del tiempo de compilación
{-# LANGUAGE TemplateHaskell #-}
import Concat
f = $("This is a very long string" <++>
"which spans over several lines")
Incluso puede verificar en ghc utilizando -ddump-splices
que la cadena concatenada se genera en el momento de la compilación.