On Fri, Jul 9, 2010 at 4:18 PM, Claus Reinke
<claus.reinke@talk21.com> wrote:
The idea would be to provide both IntMap and IntMap',
the latter being strict in the keys. There would be one
strict in the values, of course..
So instead of choosing between function' and function
(doubling the API size) or between Data.IntMap.strict
and Data.IntMap.nonstrict, clients would simply choose between IntMap' and IntMap (even a conversion could
be offered - just another specialisation of map). This module is small enough that one can compare
the core output (-ddump-simpl), and it looks as if
the -O2 compiled core for the specialized versions
of mapL matches that for the handcoded versions.
No manual duplication, just pragmas, same code
and API, just different types for the two use cases.
Since I don't have much practice reading core, it would
be good if those of you with more core experience could check this assertion; also on whether there is any reason
to expect difficulties extending this to Data.{IntMap,Map}.
Honestly I think the code duplication is more likely to yield robust,
fast code. It can be hard to make anything where the entire API goes
through a huge dictionary generate well-performing core.
foldl',
foldr' and their ilk are common enough that folks are pretty comfortable
with that convention.
mapL :: (L l a,L l b) => (a -> b) -> l a -> l b
{-# SPECIALIZE mapL :: (a -> b) -> L1 a -> L1 b #-}
{-# SPECIALIZE mapL :: (a -> b) -> L2 a -> L2 b #-}
If only the type-specialized maps would be exported
(with map instead of mapL and IntMap'/IntMap instead of L1/L2), neither the class nor the language pragmas would affect client code, so this could be a mostly
compatible extension. I'm not sure how to do that without writing more code, though - any suggestions?
Providing an entire IntMap' seems fairly drastic. Now you wind up with a
whole host of interoperability scenarios. It strikes me that the cure is worse than the disease.
-Edward Kmett