2013-02-26 12 views
12

Considerate questa funzione:L'ottimizzatore Haskell utilizza la memoizzazione per chiamate di funzioni ripetute in un ambito?

f as = if length as > 100 then length as else 100 

Poiché la funzione è puro è ovvio che la lunghezza sarà lo stesso in entrambe le chiamate. La mia domanda è: Haskell Optimizer trasforma il codice sopra in un equivalente di quanto segue?

f as = 
    let l = length as 
    in if l > 100 then l else 100 

In caso affermativo, quale impostazione di livello lo abilita? Se non lo fa, allora perché? In questo scenario uno spreco di memoria non può essere la ragione spiegata in this answer, perché la variabile introdotta viene rilasciata non appena l'esecuzione della funzione è terminata.


Si prega di notare che questo non è un duplicato di this question a causa della ambito locale, e quindi si può ottenere una risposta radicalmente diversa.

risposta

15

GHC ora è some CSE by default, poiché il flag -fcse è attivo.

Attivato per impostazione predefinita. Abilita l'ottimizzazione eliminazione sottoespressione comune. Disattivare questa opzione può essere utile se si dispone di alcune espressioni unsafePerformIO che non si desidera condividere.

Tuttavia, è conservative, a causa dei problemi con l'introduzione della condivisione (e quindi perdite di spazio). Il pass CSE riceve un bit better (e this).

Infine, si noti che esiste un plug-in per CSE completo.

Se si dispone di codice che potrebbero trarre beneficio da questo.

13

Anche in tale contesto locale, è pur sempre il caso che non sia ovvio che l'introduzione della condivisione sia sempre un'ottimizzazione. Considerate questo esempio di definizione

f = if length [1 .. 1000000] > 0 then head [1 .. 1000000] else 0 

contro questo

f = let xs = [1 .. 1000000] in if length xs > 0 then head xs else 0 

e troverete che in questo caso, il primo si comporta molto meglio, in quanto ciascuno dei calcoli eseguiti sulla lista è a buon mercato, mentre la seconda versione farà sì che la lista venga dispiegata completamente in memoria da length, e può essere scartata solo dopo che head è stato ridotto.

+3

Nonostante questo problema, ghc potrebbe essere molto più aggressivo con CSE. Devi solo avere una stima della dimensione del valore che stai CSEing. Una semplice stima è che i tipi di base occupano uno spazio trascurabile. – augustss

+0

@augusts concordato. – kosmikus

+0

In che modo 'length [1 .. 1000000]> 0' è un'operazione economica? La "lunghezza" non deve essere restituita prima che venga valutato ">"?(In ghci, l'operazione viene rallentata notevolmente quando aumentano le dimensioni della lista) –