2014-11-19 9 views
19

Dato:La fusione può vedere attraverso i wrapper newtype?

newtype MyVec = MyVec { unVec :: Data.Vector } 
    deriving (Functor, etc) 

Questo creerà (qualcosa di simile) questo:

instance Functor MyVec where 
    fmap f = MyVec . Data.Vector.fmap f . unVec 

Will Vettori regole di fusione del fuoco e riscrivere fmap f . fmap g $ myVec in fmap (f . g) myVec?

Ci sono delle insidie ​​di cui dovrei essere a conoscenza? Afaik il problema in cui si "paga" per i nuovi tipi di contenitori è stato risolto in GHC 7.8, vero?

risposta

16

Le regole di fusione operano su funzioni, non su tipi. Le tue funzioni su MyVec non avranno regole di fusione, a meno che tu non le scriva per riutilizzare quelle sottostanti.

E.g.

map :: (a -> b) -> MyVec a -> MyVec b 
map f = MyVec . Vector.map f . unVec 
{-# INLINE map #-} 

Poi ci piacerebbe avere usi:

map f . map g 

che sarà in linea per:

MyVec . Vector.map f . unVec . MyVec . Vector.map g . unVec 

GHC dovrebbe quindi cancellare il costruttore newtype, ottenendo un flusso regolare, adatto per la fusione:

MyVec . Vector.map f . Vector.map g . unVec 

È possibile confermalo eseguendo GHC e osservando l'attivazione delle regole di riscrittura. In alternativa, è possibile aggiungere la propria regola di riscrittura "MyVec. UnVec", ma GHC dovrebbe già coprirlo.

+0

[Il wiki Haskell] (https://www.haskell.org/haskellwiki/Performance/Data_types#Newtypes) afferma che "' newtype's non costa nulla ". Non dovrebbe essere riformulato se è davvero il caso che impediscono alcune ottimizzazioni? – gallais

+0

Se la definizione di 'map' non ha una chiamata a' MyVec' in essa, ad es. 'map f x = MyVec $ Vector.map f (unVec x) '? – ErikR

+1

Prima domanda: come scoprire le regole di riscrittura pertinenti. Quando uso '-ddump-rule-firings' vedo migliaia di licenziamenti ... E se sono rilevanti? – fho

Problemi correlati