问题
Given:
newtype MyVec = MyVec { unVec :: Data.Vector }
deriving (Functor, etc)
This will create (something like) this:
instance Functor MyVec where
fmap f = MyVec . Data.Vector.fmap f . unVec
Will Vectors fusion rules fire and rewrite fmap f . fmap g $ myVec
into fmap (f . g) myVec
?
Are there any pitfalls I should be aware of? Afaik the problem where you "pay" for new types in containers was solved in GHC 7.8, was it?
回答1:
Fusion rules operate on functions, not on types. Your functions on MyVec won't have fusion rules, unless you write them to reuse the underlying ones.
E.g.
map :: (a -> b) -> MyVec a -> MyVec b
map f = MyVec . Vector.map f . unVec
{-# INLINE map #-}
Then we'd have uses:
map f . map g
which will inline to:
MyVec . Vector.map f . unVec . MyVec . Vector.map g . unVec
GHC should then erase the newtype constructor, yielding a regular stream, suitable for fusion:
MyVec . Vector.map f . Vector.map g . unVec
You can confirm this by running GHC and looking at the rewrite rules firing. Alternatively, you can add your own "MyVec. unVec" rewrite rule, but GHC should already cover that.
来源:https://stackoverflow.com/questions/27014235/can-fusion-see-through-newtype-wrappers