
Hi! I was surprised not to find any documentation regarding interactions of Ord and Bounded. Are there any instances where minBound <= x == True and maxBound >= x == True don't hold for every x? Possibly relatedly, I was looking for Bounded instances for Maybe and Either. To me the following instances seem sensible: instance Bounded a => Bounded (Maybe a) where minBound = Nothing maxBound = Just maxBound instance (Bounded a, Bounded b) => Bounded (Either a b) where minBound = Left minBound maxBound = Right maxBound Are these instances omitted for a reason? Interestingly, both types do have corresponding Ord instances. Lastly, I noticed that Natural has a lower bound (0) but not an upper one, and therefore cannot have a Bounded instance. Is anyone aware of some prior art regarding a LowerBounded class or similar? Cheers, Simon

On Mon, 4 May 2020, Simon Jakobi via Libraries wrote:
Possibly relatedly, I was looking for Bounded instances for Maybe and Either. To me the following instances seem sensible:
instance Bounded a => Bounded (Maybe a) where minBound = Nothing maxBound = Just maxBound
instance (Bounded a, Bounded b) => Bounded (Either a b) where minBound = Left minBound maxBound = Right maxBound
Are these instances omitted for a reason? Interestingly, both types do have corresponding Ord instances.
Unfortunately, Ord is dual use: 1. Comparison for magnitude as suggested by the mathematical symbols (<) and (>). 2. Some arbitrary but total order for use in Set and Map. E.g. Set (Complex a) makes total sense, but 1:+0 > 0:+1 is unexpected. Ord instances on pairs is sensible for Set and Map, but (max (1,0) (0,1) == (1,0)) is strange. I would not interpret too much into (Bounded a => Maybe a). Nothing may mean "smaller than any Just element", but it may also mean "larger than any Just element" or "no regular element at all". Consider a refactoring where a numeric value is extended by Maybe. Do we want that comparisons and bounds are silently re-interpreted or would we like to be alerted that comparisons and bounds don't make sense anymore? I'd prefer the alert. Unfortunately, Ord Maybe is already defined. For an extra largest or smallest element I would define a custom Maybe-like datatype.

Dear Henning, Thank you for your response! I think I have caused some confusion by not being quite clear in my email. Sorry! base _does_ contain Ord instances for both Maybe and Either. So the question of what the smallest (Maybe Int8) is, is settled: It's Nothing. My question is, why the corresponding Bounded instances are missing from base. After all they could simply re-use the bounds implied by the Ord instances. Thanks, Simon Am Mo., 4. Mai 2020 um 15:30 Uhr schrieb Henning Thielemann < lemming@henning-thielemann.de>:
On Mon, 4 May 2020, Simon Jakobi via Libraries wrote:
Possibly relatedly, I was looking for Bounded instances for Maybe and Either. To me the following instances seem sensible:
instance Bounded a => Bounded (Maybe a) where minBound = Nothing maxBound = Just maxBound
instance (Bounded a, Bounded b) => Bounded (Either a b) where minBound = Left minBound maxBound = Right maxBound
Are these instances omitted for a reason? Interestingly, both types do have corresponding Ord instances.
Unfortunately, Ord is dual use:
1. Comparison for magnitude as suggested by the mathematical symbols (<) and (>).
2. Some arbitrary but total order for use in Set and Map.
E.g. Set (Complex a) makes total sense, but 1:+0 > 0:+1 is unexpected. Ord instances on pairs is sensible for Set and Map, but (max (1,0) (0,1) == (1,0)) is strange.
I would not interpret too much into (Bounded a => Maybe a). Nothing may mean "smaller than any Just element", but it may also mean "larger than any Just element" or "no regular element at all".
Consider a refactoring where a numeric value is extended by Maybe. Do we want that comparisons and bounds are silently re-interpreted or would we like to be alerted that comparisons and bounds don't make sense anymore? I'd prefer the alert. Unfortunately, Ord Maybe is already defined.
For an extra largest or smallest element I would define a custom Maybe-like datatype.

On Mon, 4 May 2020, Simon Jakobi wrote:
base _does_ contain Ord instances for both Maybe and Either. So the question of what the smallest (Maybe Int8) is, is settled: It's Nothing.
I know and I think I indicated that. I'd prefer to remove instance Ord Maybe rather than extend instances to Bounded. Sure, instance Ord Maybe is settled and there is no alternate Ord for Set, so removal is currently not an option. However, not defining Bounded Maybe seems most sound to me.

Apologies! I should have read your email properly before responding! Am Mo., 4. Mai 2020 um 15:49 Uhr schrieb Henning Thielemann < lemming@henning-thielemann.de>:
On Mon, 4 May 2020, Simon Jakobi wrote:
base _does_ contain Ord instances for both Maybe and Either. So the question of what the smallest (Maybe Int8) is, is settled: It's Nothing.
I know and I think I indicated that. I'd prefer to remove instance Ord Maybe rather than extend instances to Bounded. Sure, instance Ord Maybe is settled and there is no alternate Ord for Set, so removal is currently not an option. However, not defining Bounded Maybe seems most sound to me.

Dear Henning, I've re-read your email now and thought about it a bit more.
Unfortunately, Ord is dual use:
1. Comparison for magnitude as suggested by the mathematical symbols (<) and (>).
2. Some arbitrary but total order for use in Set and Map.
E.g. Set (Complex a) makes total sense, but 1:+0 > 0:+1 is unexpected. Ord instances on pairs is sensible for Set and Map, but (max (1,0) (0,1) == (1,0)) is strange.
Personally, I find nothing strange about (max (1,0) (0,1) == (1,0)), but I started wondering how other languages handle these examples. I tried Python: $ python3 Python 3.5.2 (default, Apr 16 2020, 17:47:17) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information.
max((1,0),(0,1)) (1, 0) complex(1,0) > complex(0,1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: complex() > complex()
I also find the Ord Maybe instance quite intuitive: "Nothing is less than something (Just)" It is also consistent with the interpretation of Maybe as a list of at most one element: $ ghci
[] < [()] True
So in my view the Bounded Maybe instance still seems like a good idea. Cheers, Simon

The Bounded class is broken because it combines two distinct concepts:
BoundedAbove and BoundedBelow. If Maybe is to have instances similar
to what it has now, they should surely look like
instance BoundedBelow (Maybe a) where
minBound = Nothing
instance BoundedAbove a => BoundedAbove (Maybe a) where
maxBound = Just maxBound
On Wed, May 6, 2020 at 1:52 PM Simon Jakobi via Libraries
Dear Henning,
I've re-read your email now and thought about it a bit more.
Unfortunately, Ord is dual use:
1. Comparison for magnitude as suggested by the mathematical symbols (<) and (>).
2. Some arbitrary but total order for use in Set and Map.
E.g. Set (Complex a) makes total sense, but 1:+0 > 0:+1 is unexpected. Ord instances on pairs is sensible for Set and Map, but (max (1,0) (0,1) == (1,0)) is strange.
Personally, I find nothing strange about (max (1,0) (0,1) == (1,0)), but I started wondering how other languages handle these examples. I tried Python:
$ python3 Python 3.5.2 (default, Apr 16 2020, 17:47:17) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information.
max((1,0),(0,1)) (1, 0) complex(1,0) > complex(0,1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: complex() > complex()
I also find the Ord Maybe instance quite intuitive: "Nothing is less than something (Just)"
It is also consistent with the interpretation of Maybe as a list of at most one element:
$ ghci
[] < [()] True
So in my view the Bounded Maybe instance still seems like a good idea.
Cheers, Simon _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Thanks David,
I agree that having separate type classes for lower and upper bounds
would be the better design.
I really like your names, BoundedBelow and BoundedAbove, too!
Am Mi., 6. Mai 2020 um 21:13 Uhr schrieb David Feuer
The Bounded class is broken because it combines two distinct concepts: BoundedAbove and BoundedBelow. If Maybe is to have instances similar to what it has now, they should surely look like
instance BoundedBelow (Maybe a) where minBound = Nothing instance BoundedAbove a => BoundedAbove (Maybe a) where maxBound = Just maxBound
On Wed, May 6, 2020 at 1:52 PM Simon Jakobi via Libraries
wrote: Dear Henning,
I've re-read your email now and thought about it a bit more.
Unfortunately, Ord is dual use:
1. Comparison for magnitude as suggested by the mathematical symbols (<) and (>).
2. Some arbitrary but total order for use in Set and Map.
E.g. Set (Complex a) makes total sense, but 1:+0 > 0:+1 is unexpected. Ord instances on pairs is sensible for Set and Map, but (max (1,0) (0,1) == (1,0)) is strange.
Personally, I find nothing strange about (max (1,0) (0,1) == (1,0)), but I started wondering how other languages handle these examples. I tried Python:
$ python3 Python 3.5.2 (default, Apr 16 2020, 17:47:17) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information.
max((1,0),(0,1)) (1, 0) complex(1,0) > complex(0,1) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unorderable types: complex() > complex()
I also find the Ord Maybe instance quite intuitive: "Nothing is less than something (Just)"
It is also consistent with the interpretation of Maybe as a list of at most one element:
$ ghci
[] < [()] True
So in my view the Bounded Maybe instance still seems like a good idea.
Cheers, Simon _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Am Mi., 6. Mai 2020 um 21:13 Uhr schrieb David Feuer : The Bounded class is broken because it combines two distinct concepts:
BoundedAbove and BoundedBelow. Indeed, having that distinction would be useful. Just to add some
bikeshedding regarding the names:
* HasInfimum / HasSupremum or
* HasInitialObject / HasTerminalObject or shorter
* HasInitial / HasTerminal (maybe a bit too short)
I wouldn't be too surprised if Edward K. already has something like this on
Hackage. :-) If Maybe is to have instances similar
to what it has now, they should surely look like instance BoundedBelow (Maybe a) where
minBound = Nothing
instance BoundedAbove a => BoundedAbove (Maybe a) where
maxBound = Just maxBound Well, choosing Nothing to be the infimum is rather arbitrary, you could as
well define:
instance BoundedBelow a => BoundedBelow (Maybe a) where
minBound = Just minBound
instance BoundedAbove (Maybe a) where
maxBound = Nothing
But the previous definition is probably a better fit given the Ord
instance, nevertheless. the choice *is* arbitrary. Perhaps Maybe should not
be an instance of either class?

On Mon, May 4, 2020 at 7:55 AM Simon Jakobi via Libraries
Are there any instances where
minBound <= x == True
and
maxBound >= x == True
don't hold for every x?
Yes: minBound <= Data.Ord.Down (1 :: Int) == False IMO, this is kind of a wart in Down, as I commented at https://gitlab.haskell.org/ghc/ghc/-/merge_requests/881#note_271111 Joseph C. Sible

I'd call that a bug in the Down instance myself, and a serious one!
On Sat, May 9, 2020, 5:30 PM Joseph C. Sible
On Mon, May 4, 2020 at 7:55 AM Simon Jakobi via Libraries
wrote: Are there any instances where
minBound <= x == True
and
maxBound >= x == True
don't hold for every x?
Yes:
minBound <= Data.Ord.Down (1 :: Int) == False
IMO, this is kind of a wart in Down, as I commented at https://gitlab.haskell.org/ghc/ghc/-/merge_requests/881#note_271111
Joseph C. Sible _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Agreed. The min of a total order should be the min. This seems to be a
straight up bug.
On Sat, May 9, 2020 at 5:34 PM David Feuer
I'd call that a bug in the Down instance myself, and a serious one!
On Sat, May 9, 2020, 5:30 PM Joseph C. Sible
wrote: On Mon, May 4, 2020 at 7:55 AM Simon Jakobi via Libraries
wrote: Are there any instances where
minBound <= x == True
and
maxBound >= x == True
don't hold for every x?
Yes:
minBound <= Data.Ord.Down (1 :: Int) == False
IMO, this is kind of a wart in Down, as I commented at https://gitlab.haskell.org/ghc/ghc/-/merge_requests/881#note_271111
Joseph C. Sible _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

The question of the Enum instance is left a bit unsatisfactory. It can
either match the Num instance or the Bounded instance but not both. Ugh!
On Sat, May 9, 2020, 5:51 PM Carter Schonwald
Agreed. The min of a total order should be the min. This seems to be a straight up bug.
On Sat, May 9, 2020 at 5:34 PM David Feuer
wrote: I'd call that a bug in the Down instance myself, and a serious one!
On Sat, May 9, 2020, 5:30 PM Joseph C. Sible
wrote: On Mon, May 4, 2020 at 7:55 AM Simon Jakobi via Libraries
wrote: Are there any instances where
minBound <= x == True
and
maxBound >= x == True
don't hold for every x?
Yes:
minBound <= Data.Ord.Down (1 :: Int) == False
IMO, this is kind of a wart in Down, as I commented at https://gitlab.haskell.org/ghc/ghc/-/merge_requests/881#note_271111
Joseph C. Sible _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries

Best solution, IMO: don't give Down a Num instance.
On Sat, May 9, 2020, 5:55 PM David Feuer
The question of the Enum instance is left a bit unsatisfactory. It can either match the Num instance or the Bounded instance but not both. Ugh!
On Sat, May 9, 2020, 5:51 PM Carter Schonwald
wrote: Agreed. The min of a total order should be the min. This seems to be a straight up bug.
On Sat, May 9, 2020 at 5:34 PM David Feuer
wrote: I'd call that a bug in the Down instance myself, and a serious one!
On Sat, May 9, 2020, 5:30 PM Joseph C. Sible
wrote: On Mon, May 4, 2020 at 7:55 AM Simon Jakobi via Libraries
wrote: Are there any instances where
minBound <= x == True
and
maxBound >= x == True
don't hold for every x?
Yes:
minBound <= Data.Ord.Down (1 :: Int) == False
IMO, this is kind of a wart in Down, as I commented at https://gitlab.haskell.org/ghc/ghc/-/merge_requests/881#note_271111
Joseph C. Sible _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
participants (6)
-
Carter Schonwald
-
David Feuer
-
Henning Thielemann
-
Joseph C. Sible
-
Simon Jakobi
-
Sven Panne