The containers package has Data.Map.Strict and Data.IntMap.Strict, offering functions for handling maps that are strict in the values stored. But these modules are lies, as comments in the source explain:
-- API of this module is strict in the keys, but lazy in the values.
-- If you need value-strict maps, use "Data.Map.Strict" instead.
-- The 'Map' type itself is shared between the lazy and strict modules,
-- meaning that the same 'Map' value can be passed to functions in
-- both modules (although that is rarely needed).
-- Be aware that the 'Functor', 'Traversable' and 'Data' instances
-- are the same as for the "Data.Map.Lazy" module, so if they are used
-- on strict maps, the resulting maps will be lazy.
Yuck. This is not nice. Clearly, the current interfaces need to stay around for compatibility, but I think we should add some unbroken ones too. There are two and a half sane ways to do this:
1. Make strict types that just wrap the lazy ones in newtype wrappers. The benefits: a) They can reuse all the code from Data.Map.Strict or Data.IntMap.Strict, producing tiny little wrapper modules. b) They can support cheap strictToLazy and unsafeLazyToStrict operations (newtype unwrappers/wrappers). c) They support lazyToStrict operations with no significant new code (reusing the NFData code).