2013-07-07 13 views
21

Haskell 2010 garantisce la concatenazione di stringhe letterali al momento della compilazione?Haskell concatena stringhe letterali in fase di compilazione?

Se ho

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

fa il compilatore a trattare come

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

voglio tenere le mie linee di sorgente di lunghezza inferiore a 80 caratteri, se possibile, ma io non voglio introdurre inefficienza di runtime.

risposta

16

Utilizzare un gap-una sequenza di uno o più caratteri di spaziatura tra barre rovesciate:

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

L'equivalente zero larghezza è \&, utile per separare escape numerici da caratteri numerici:

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

Haskell 2010 garantisce che è denotazionalmente equivalente alla stringa unita, ma non ha nulla da dire su come dovrebbe essere compilato. È abbastanza facile controllare con lo strumento ghc-core, però.

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

e quando si corre 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" 

... 

e vediamo che la stringa è stata fusa nella lingua intermedia Nucleo.


Modifica: Per sottolineare il mio accordo con le altre risposte, proprio perché questo programma particolare, ha un core dump con la stringa risultante dalla fusione non garantisce che il compilatore lo farà per tutte le stringhe. Essere conformi alle specifiche Haskell non implica molto su come le cose vengono compilate.

+0

Un'attenta sull'utilizzo del "core dump" per la stampa del core code intermedio :-) – David

+0

Forse ho trasmesso un senso artificiale di quanto sia facile sbirciare al core e imparare come stanno le cose ... ma! Ho spesso trovato che non sia così difficile. All'inizio scoraggiante. –

19

Haskell 2010 garantisce la concatenazione di stringhe letterali al momento della compilazione?

No.

efficienza runtime è lontano dal campo di applicazione Haskell2010. Non vogliamo vietare le implementazioni sperimentali solo perché sono lente.

Inoltre, dire che cosa dovrebbe essere fatto durante il periodo di compilazione potrebbe causare problemi agli interpreti, come gli abbracci.

Infine, è utile dare una certa libertà agli implementatori. Forse in alcune strane circostanze sarebbe più veloce non precompilare la stringa?

Haskell 2010 parla del tempo di compilazione solo nel contesto degli errori. (Ad esempio, errori di tipo sono garantiti per essere in fase di compilazione.)

4

Non è questo che haskell garantisce. Potrebbero esserci dei compilatori come ghc che eseguono questa ottimizzazione, ma non esiste uno standard che lo preservi. Quindi potrebbe accadere che in una versione futura questa ottimizzazione potrebbe non verificarsi.

Perché non utilizzare Template Haskell se si vuole veramente garantire che sia fatto in fase di compilazione.Seguendo l'esempio è testato su GHC, ma penso che si può farlo funzionare su altri compilatori anche:

In un file di modulo si può avere un codice come questo

module Concat where 
import Language.Haskell.TH 

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

Poi nel file di cui si richiede alla realtà fare la compilazione tempo concatenazione

{-# LANGUAGE TemplateHaskell #-} 
import Concat 

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

è anche possibile controllare in ghc utilizzando -ddump-splices che la stringa concatenata viene generata in fase di compilazione.

+5

C'è anche il [Povero documento di molti qui] (http://www.haskell.org/haskellwiki/Poor_man's_here_document) che usa giunzioni invece di operatori in linea. –

+0

@tel Grazie. Sembra molto meglio da usare. – Satvik