Changes to IntMap
August 1, 2011As it stands, it is impossible to define certain value-strict operations on IntMaps with the current containers API. The reader is invited, for example, to try efficiently implementing map :: (a -> b) -> IntMap a -> IntMap b, in such a way that for a non-bottom and non-empty map m, Data.IntMap.map (\_ -> undefined) m == undefined.
Now, we could have just added a lot of apostrophe suffixed operations to the existing API, which would have greatly blown it up in size, but following conversation on libraries@haskell.org, we’ve decided we will be splitting up the module into two modules: Data.IntMap.Strict and Data.IntMap.Lazy. For backwards compatibility, Data.IntMap will be the lazy version of the module, and the current value-strict functions residing in this module will be deprecated.
The details of what happened are a little subtle. Here is the reader’s digest version:
- The
IntMapinData.IntMap.Strictand theIntMapinData.IntMap.Lazyare exactly the same map; there is no runtime or type level difference between the two. The user can swap between “implementations” by importing one module or another, but we won’t prevent you from using lazy functions on strict maps. You can convert lazy maps to strict ones usingseqFoldable. - Similarly, if you pass a map with lazy values to a strict function, the function will do the maximally lazy operation on the map that would still result in correct operation in the strict case. Usually, this means that the lazy value probably won’t get evaluated… unless it is.
- Most type class instances remain valid for both strict and lazy maps, however,
FunctorandTraversabledo not have valid “strict” versions which obey the appropriate laws, so we’ve selected the lazy implementation for them. - The lazy and strict folds remain, because whether or not a fold is strict is independent of whether or not the data structure is value strict or spine strict.
I hacked up a first version for the strict module at Hac Phi on Sunday, you can see it here. The full implementation can be found here.
Would this be a good time to merge in the functionality of
http://hackage.haskell.org/package/enummapset
into the
containerspackage?Data.IntMap.map (\_ -> undefined) m == undefinedholds for every (in fact, for any) non-bottomm, then it also holds for a bottom one, by monotonicity. So I don’t see a need for that constraint.