Data.IntMap/IntSet inconsistencies

The interfaces from Data.IntMap and Data.Map are subtly different. Here are two issues: 1. deleteMin/Max raise an exception on empty maps/set > Data.Map.deleteMax Data.Map.empty fromList [] > Data.IntMap.deleteMax Data.IntMap.empty fromList *** Exception: deleteMax: empty map has no maximal element > Data.Set.deleteMin Data.Set.empty fromList [] > Data.IntSet.deleteMin Data.IntSet.empty fromList *** Exception: deleteMin: empty set has no minimal element Proposal: Data.IntMap/IntSet.deleteMin/Max should return empty when the input is empty. 2. findMin/Max have a different signature Data.Map.findMin :: Map k a -> (k, a) Data.IntMap.findMin :: IntMap a -> a The documentation of IntMap.findMin is also incorrect, it reads: /O(log n)/ The minimal key of the map. While it returns the value associated with the minimal key. Proposal: Data.IntMap.findMin/findMax should have the type IntMap a -> (Key,a) Twan

Excerpts from Twan van Laarhoven's message of Sun Nov 01 23:00:34 +0100 2009:
The interfaces from Data.IntMap and Data.Map are subtly different. Here are two issues:
Both issues are real, and both solutions are reasonable. I support them. -- Nicolas Pouillard http://nicolaspouillard.fr

+1.
I'm somewhat leery of the interface change on #2, but I thnk consistency is
warranted and the burden of fixing it would only get worse with time.
-Edward Kmett
On Sun, Nov 1, 2009 at 5:00 PM, Twan van Laarhoven
The interfaces from Data.IntMap and Data.Map are subtly different. Here are two issues:
1. deleteMin/Max raise an exception on empty maps/set
Data.Map.deleteMax Data.Map.empty fromList [] Data.IntMap.deleteMax Data.IntMap.empty fromList *** Exception: deleteMax: empty map has no maximal element
Data.Set.deleteMin Data.Set.empty fromList [] Data.IntSet.deleteMin Data.IntSet.empty fromList *** Exception: deleteMin: empty set has no minimal element
Proposal: Data.IntMap/IntSet.deleteMin/Max should return empty when the input is empty.
2. findMin/Max have a different signature
Data.Map.findMin :: Map k a -> (k, a) Data.IntMap.findMin :: IntMap a -> a
The documentation of IntMap.findMin is also incorrect, it reads:
/O(log n)/ The minimal key of the map.
While it returns the value associated with the minimal key.
Proposal: Data.IntMap.findMin/findMax should have the type IntMap a -> (Key,a)
Twan _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On 1 Nov 2009, at 22:00, Twan van Laarhoven wrote:
The interfaces from Data.IntMap and Data.Map are subtly different.
Proposal: Data.IntMap/IntSet.deleteMin/Max should return empty when the input is empty.
Proposal: Data.IntMap.findMin/findMax should have the type IntMap a -> (Key,a)
+1 for consistency. Regards, Malcolm

Also +1. On a related note, I think it's unfortunate that those functions are partial. Like List.minimum and maximum, I always wind up wrapping them in a function that provides a default value. I suppose that would be a different proposal though... but maybe if we're breaking compatibility anyway it would be a good time to, say, change them to 'IntMap k a -> (k, a) -> (k, a)'? Actually, it seems that often 'IntMap k a -> b -> ((k, a) -> b) -> b' is more convenient, e.g. 'findMax fm Nothing Just', and you can always get the default val version back with 'id'.

On Mon, Nov 2, 2009 at 12:14 PM, Evan Laforge
Also +1.
On a related note, I think it's unfortunate that those functions are partial. Like List.minimum and maximum, I always wind up wrapping them in a function that provides a default value.
I suppose that would be a different proposal though... but maybe if we're breaking compatibility anyway it would be a good time to, say, change them to 'IntMap k a -> (k, a) -> (k, a)'? Actually, it seems that often 'IntMap k a -> b -> ((k, a) -> b) -> b' is more convenient, e.g. 'findMax fm Nothing Just', and you can always get the default val version back with 'id'.
I would prefer that partial functions return 'Maybe' - then I can pick whether or not I want 'Prelude.maybe' behavior or 'Data.Maybe.fromMaybe' behavior. I would prefer seeing findMax :: Map k a -> Maybe (k, a). It's also easier to read the function signature and know what is going to happen, rather than giving the function three parameters. But it sounds like we need a different ticket. Antoine

I would prefer that partial functions return 'Maybe' - then I can pick whether or not I want 'Prelude.maybe' behavior or 'Data.Maybe.fromMaybe' behavior. I would prefer seeing findMax :: Map k a -> Maybe (k, a).
It's also easier to read the function signature and know what is going to happen, rather than giving the function three parameters.
Sure, this is reasonable too. [ ross ]
Proposal: deprecate and then remove find, findIndex, findMin, findMax, deleteFindMin and deleteFindMax.
List.find? No thanks, I use that all the time. As far as findMin, toAscList works just as well, so fine, let's kill it. For findMax, toDescList, which I thought was patched in a year ago, still doesn't appear in the latest version of collections, so as far as I know there's no alternative for it. As far as findIndex, are there any known uses for indexed Maps? I haven't used it but maybe there's some important use I don't know about.

On Mon, Nov 02, 2009 at 01:30:49PM -0700, Evan Laforge wrote:
[ ross ]
Proposal: deprecate and then remove find, findIndex, findMin, findMax, deleteFindMin and deleteFindMax.
List.find? No thanks, I use that all the time.
No, Data.(Int)Map.find
For findMax, toDescList, which I thought was patched in a year ago, still doesn't appear in the latest version of collections, so as far as I know there's no alternative for it.
Containers is a core package, so it's tied to GHC's release cycle: one major release per year and only bugfixes between them.

On Mon, Nov 2, 2009 at 1:57 PM, Ross Paterson
On Mon, Nov 02, 2009 at 01:30:49PM -0700, Evan Laforge wrote:
[ ross ]
Proposal: deprecate and then remove find, findIndex, findMin, findMax, deleteFindMin and deleteFindMax.
List.find? No thanks, I use that all the time.
No, Data.(Int)Map.find
Yeah, I can't find it on http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Map.ht.... What's the signature?
For findMax, toDescList, which I thought was patched in a year ago, still doesn't appear in the latest version of collections, so as far as I know there's no alternative for it.
Containers is a core package, so it's tied to GHC's release cycle: one major release per year and only bugfixes between them.
I see, yet another reason to look forward to 6.12 :)

On Mon, Nov 02, 2009 at 03:17:13PM -0800, Evan Laforge wrote:
On Mon, Nov 2, 2009 at 1:57 PM, Ross Paterson
wrote: On Mon, Nov 02, 2009 at 01:30:49PM -0700, Evan Laforge wrote:
[ ross ]
Proposal: deprecate and then remove find, findIndex, findMin, findMax, deleteFindMin and deleteFindMax.
List.find? No thanks, I use that all the time.
No, Data.(Int)Map.find
Yeah, I can't find it on http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Map.ht.... What's the signature?
My mistake: it's a private version of (!).

Yeah, I can't find it on http://www.haskell.org/ghc/docs/latest/html/libraries/containers/Data-Map.ht.... What's the signature?
My mistake: it's a private version of (!).
Ahh, kill away then. I wouldn't mind removing (!) too as long as we're deprecating things :) In the presence of toDescList I agree findMax can go away.

Evan Laforge wrote:
As far as findMin, toAscList works just as well, so fine, let's kill it. For findMax, toDescList, which I thought was patched in a year ago, still doesn't appear in the latest version of collections, so as far as I know there's no alternative for it.
The fact that a function can be written in terms of other things in the library is no excuse not to include it. If a program somewhere needs to find the smallest key in a map, then it should say so! findMin makes the intention of the programmer clear, while toAscList does not. Twan

On Tue, Nov 03, 2009 at 12:43:41AM +0100, Twan van Laarhoven wrote:
The fact that a function can be written in terms of other things in the library is no excuse not to include it. If a program somewhere needs to find the smallest key in a map, then it should say so! findMin makes the intention of the programmer clear, while toAscList does not.
The safe alternative is minViewWithKey.

On Sun, Nov 01, 2009 at 11:00:34PM +0100, Twan van Laarhoven wrote:
2. findMin/Max have a different signature
Data.Map.findMin :: Map k a -> (k, a) Data.IntMap.findMin :: IntMap a -> a
This part is already fixed in 6.12/HEAD: Prelude> :t Data.IntMap.findMin Data.IntMap.findMin :: Data.IntMap.IntMap a -> (Int, a) Thanks Ian

On Sun, Nov 01, 2009 at 11:00:34PM +0100, Twan van Laarhoven wrote:
Proposal: Data.IntMap/IntSet.deleteMin/Max should return empty when the input is empty.
Yes, and also for updateMinWithKey and updateMaxWithKey.
Proposal: Data.IntMap.findMin/findMax should have the type IntMap a -> (Key,a)
Proposal: deprecate and then remove find, findIndex, findMin, findMax, deleteFindMin and deleteFindMax.
participants (8)
-
Antoine Latter
-
Edward Kmett
-
Evan Laforge
-
Ian Lynagh
-
Malcolm Wallace
-
Nicolas Pouillard
-
Ross Paterson
-
Twan van Laarhoven