Proposal #2560 again: add newtype Down/ReverseOrd to Data.Ord

Hello list, About two and a half months ago I proposed that the following newtype (under the name "Down") be added to Data.Ord: newtype ReverseOrd a = ReverseOrd { getReverseOrd :: a } instance Ord ReverseOrd where a <= b = getReverseOrd b <= getReverseOrd a -- other methods, etc. I never followed up to that post, so I am doing that now. Since the discussion period has ended, let me summarize of responses: 1. Everyone is in favor of adding it 2. There is some criticism of the name 3. Some people (apfelmus) didn't like the getReverseOrd function As an alternative name, Isaac suggested "Reverse", "ReverseOrd" or "Opposite". I don't really like the name "Reverse", because that can mean many things: reversing a list, reverse order of composition, inverse/reverse a relation, etc. Although it is a bit verbose, "ReverseOrd" is the most clear. Concerning the "get" function: there is lots precedence in - Monoid wrappers (Sum, Product, Endo, etc.) - Applicative wrappers (ZipList, Const, etc.) - mtl types (State, Reader, etc.), To resolve the naming bikeshed issue, and because it has been a long time since the discussion ended, I propose an additional discussion period of 1 week, ending January 13. Twan

Twan van Laarhoven
About two and a half months ago I proposed that the following newtype (under the name "Down") be added to Data.Ord:
newtype ReverseOrd a = ReverseOrd { getReverseOrd :: a }
instance Ord ReverseOrd where a <= b = getReverseOrd b <= getReverseOrd a -- other methods, etc.
[...]
I don't really like the name "Reverse",
Me neither... How about: -- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq instance Ord a => Ord (Dual a) where Dual x <= Dual y = y <= x Dual x < Dual y = y < x Dual x >= Dual y = y >= x Dual x > Dual y = y > x Dual x `compare` Dual y = y `compare` x Dual x `min` Dual y = y `max` x Dual x `max` Dual y = y `min` x Wolfram

kahl@cas.mcmaster.ca wrote:
Me neither...
How about:
-- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq
In my opinion "dual" is even worse: - "dual" is not a name that people think about when they want something sorted in descending order or they want a different priority queue, etc. I think of names like "reverse", "descending" and "something to do with order". - "dual" can mean many more things. First of all there are different dualities in mathematics, I guess this refers to the categorical dual. Then there are many ways to use that duality in Haskell. The first thing that comes to mind, and which is a closer fit, is newtype Op t a b = Op (t b a), the dual of a Control.Category style category. Twan

Twan wrote:
kahl@cas.mcmaster.ca wrote:
-- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq
In my opinion "dual" is even worse:
"opposite"? I'm also happy with anything suggested already. Ganesh ============================================================================== Please access the attached hyperlink for an important electronic communications disclaimer: http://www.credit-suisse.com/legal/en/disclaimer_email_ib.html ==============================================================================

FlipOrd { unFlipOrd :: a } ? --S On Jan 6, 2009, at 10:58 AM, Twan van Laarhoven wrote:
kahl@cas.mcmaster.ca wrote:
Me neither... How about: -- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq
In my opinion "dual" is even worse:
- "dual" is not a name that people think about when they want something sorted in descending order or they want a different priority queue, etc. I think of names like "reverse", "descending" and "something to do with order".
- "dual" can mean many more things. First of all there are different dualities in mathematics, I guess this refers to the categorical dual. Then there are many ways to use that duality in Haskell. The first thing that comes to mind, and which is a closer fit, is newtype Op t a b = Op (t b a), the dual of a Control.Category style category.
Twan _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Twan van Laarhoven
kahl@cas.mcmaster.ca wrote:
Me neither...
How about:
-- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq
[...]
- "dual" can mean many more things.
Exactly --- that's why I propose qualified import, so one would use, e.g.: sort . map Ord.Dual clarifying that one is using the dual Ord instance. (Ordering duality is about the fact that the converse of an ordering relation is an ordering relation again; the Haskell type class |Ord| is the special case of linear orderings. ) This is standard terminology, and I think we should encourage such use of standard terminology and concepts. Of course, alternatives remain available, in the spirit of Henning Thielemann's ``Warm, fuzzy thing Transformer'':
It was argued that people avoid Haskell because of terms from Category theory like 'Monad'. This problem can now be solved by a wrapper which presents all the WWW without monads! Start e.g. at
;-) Wolfram

On Tue, Jan 06, 2009 at 05:15:46PM -0000, kahl@cas.mcmaster.ca wrote: [...]
Exactly --- that's why I propose qualified import, so one would use, e.g.:
sort . map Ord.Dual
clarifying that one is using the dual Ord instance. (Ordering duality is about the fact that the converse of an ordering relation is an ordering relation again; the Haskell type class |Ord| is the special case of linear orderings. )
This is standard terminology, and I think we should encourage such use of standard terminology and concepts.
In my part of the category-theory world, standard terminology is "opposite category" and thus "opposite ordering" (since a partial order is a special case of a category). But I would not be too surprised to hear "dual ordering" as well. (By the way, a much worse abuse of the name Dual already exists in Data.Monoid, to describe the operation of flipping the arguments of the multiplication in a monoid. This should certainly be called the opposite monoid. Google for "dual monoid" and you will find that all uses of that term are for other concepts.)
Of course, alternatives remain available, in the spirit of Henning Thielemann's ``Warm, fuzzy thing Transformer'':
It was argued that people avoid Haskell because of terms from Category theory like 'Monad'. This problem can now be solved by a wrapper which presents all the WWW without monads! Start e.g. at
;-)
While "opposite" is a term used in category theory, it's also a perfectly ordinary word that has the right connotations to non-mathematicians. "Dual" is a little scary, I think. Regards, Reid

kahl@cas.mcmaster.ca schrieb:
Of course, alternatives remain available, in the spirit of Henning Thielemann's ``Warm, fuzzy thing Transformer'':
It was argued that people avoid Haskell because of terms from Category theory like 'Monad'. This problem can now be solved by a wrapper which presents all the WWW without monads! Start e.g. at
;-)
Thanks for quoting it! Btw. now you can also access it via a warmer, but less fuzzier URL: http://www.haskell.org.monadtransformer.parallelnetz.de/haskellwiki/Category... I can easily add a replacement Ord.Dual -> "Somehow different" and "Existential quantification -> Hidden type variable" ...

On Wed, 7 Jan 2009, Stefan Holdermans wrote:
Twan,
How about:
-- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq
+1 for Dual.
+1 for Dual. The term seems common in lattice theory. I use it myself. -- Russell O'Connor http://r6.ca/ ``All talk about `theft,''' the general counsel of the American Graphophone Company wrote, ``is the merest claptrap, for there exists no property in ideas musical, literary or artistic, except as defined by statute.''

On Wed, 7 Jan 2009, Stefan Holdermans wrote:
+1 for Dual. +1 for Dual. The term seems common in lattice theory. I use it myself.
Dual is horrible. The term is in general ambiguous and in this context gratuitously pseudo-technical. RevOrd, Reverse or Descending are about as good as I've heard. Bart Massey bart <at> cs.pdx.edu

roconnor@theorem.ca wrote:
On Wed, 7 Jan 2009, Stefan Holdermans wrote:
Twan,
How about:
-- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq
+1 for Dual.
+1 for Dual. The term seems common in lattice theory. I use it myself.
Dual does seem to be the right term, but I suggest using DualOrd or DualOrdering instead. The fact that it can be imported qualified is no reason to confuse people, in many cases the function will not be imported qualified, since conflicts are very unlikely. To me just "dual" does not immediatly suggest a reverse ordering. Consider also: sortBy (comparing `on` Dual . fst) stuff vs. sortBy (comparing `on` DualOrd . fst) stuff In the first version it is not immediatly clear that dual has something to do with the ordering, and not just taking some kind of dual of something in some other way. Also, the record selector should be called getDual{Ord}, in accordance with the monoid wrappers and mtl types. In summary, I like: DualOrd{ering}, ReverseOrd{ering} and am okay with Desc{ending}. Twan

Twan van Laarhoven
How about:
-- intended for |qualified| import |as Ord|: newtype Dual a = Dual { unDual :: a } deriving Eq
+1 for Dual.
+1 for Dual. The term seems common in lattice theory. I use it myself.
Dual does seem to be the right term, but I suggest using DualOrd or DualOrdering instead. The fact that it can be imported qualified is no reason to confuse people, in many cases the function will not be imported qualified, since conflicts are very unlikely. To me just "dual" does not immediatly suggest a reverse ordering. Consider also: sortBy (comparing `on` Dual . fst) stuff vs. sortBy (comparing `on` DualOrd . fst) stuff In the first version it is not immediatly clear that dual has something to do with the ordering, and not just taking some kind of dual of something in some other way.
I plead to accelerate the already perceptible shift towards more qualified imports, and to treat the unqualified import as the exception. Ord is a particularly good candidate for that, since it is hogging the whole partial-order namespace for the special case of linear orders. In your example, if there is only one occurrence of Dual in a large module, then
sortBy (comparing `on` Ord.Dual . fst) stuff
would be natural. In other places, that module might use ``POrd.Dual''... However, if a module uses only Ord duality, and uses that a lot, then it may become more readable to use an unqualified import (still preferably with an explicit import list) and write
sortBy (comparing `on` Dual . fst) stuff
For this special case, I don't want to force qualified import, but suggest it as standard usage, leaving open the more concise second option. The decision to use ``DualOrd'' takes away the concise option, saves only one character over ``Ord.Dual'', and requires more effort to remember --- why is it not ``OrdDual''?
Also, the record selector should be called getDual{Ord}, in accordance with the monoid wrappers and mtl types.
MTL seems to suggest ``runDual'' ;-) ``get*'' sounds far too imparative for my taste. Wolfram

kahl@cas.mcmaster.ca schrieb:
I plead to accelerate the already perceptible shift towards more qualified imports, and to treat the unqualified import as the exception.
Ord is a particularly good candidate for that, since it is hogging the whole partial-order namespace for the special case of linear orders.
In your example, if there is only one occurrence of Dual in a large module, then
sortBy (comparing `on` Ord.Dual . fst) stuff
would be natural. In other places, that module might use ``POrd.Dual''...
+1
However, if a module uses only Ord duality, and uses that a lot, then it may become more readable to use an unqualified import (still preferably with an explicit import list)
See: http://www.haskell.org/haskellwiki/Import_modules_properly
and write
sortBy (comparing `on` Dual . fst) stuff
For this special case, I don't want to force qualified import, but suggest it as standard usage, leaving open the more concise second option.
+1 However I don't care about Dual vs. Opposite vs. Reverse.

Twan van Laarhoven wrote:
About two and a half months ago I proposed that the following newtype (under the name "Down") be added to Data.Ord:
newtype ReverseOrd a = ReverseOrd { getReverseOrd :: a }
instance Ord ReverseOrd where a <= b = getReverseOrd b <= getReverseOrd a -- other methods, etc.
IMHO this type is very important! I had to use a hack in my heap package [1] (see HeapPolicy class and XYPolicy phantom tpyes, they allow redefining an ordering relation), because there is no such thing in the base libraries. The aim was to make type safe distinctions between minimum- and maximum ordered heaps. With a ReverseOrd type, I could just provide a minimum ordered heap. Then it would be much more obvious, how to use the package. I'm not saying that the heap package is the one and only reason for introducinging something like ReverseOrd, but I am saying that it addresses a common problem one quickly encounters. As for the name of the newtype, I'd prefer ReverseOrd, as it best describes the intended usage: Reversing the ordering relation of a type. Other possibilities are: - FlipOrd (beacuse (flip compare) is the desired effect) - Descending[Ord] (opposed to ascending order) - Reorder (unfortunately doesn't describe how it's reordered) just my 2 cents :)
[...]
Regards, Stephan [1] http://hackage.haskell.org/cgi-bin/hackage-scripts/package/heap -- Früher hieß es ja: Ich denke, also bin ich. Heute weiß man: Es geht auch so. - Dieter Nuhr
participants (10)
-
Bart Massey
-
Henning Thielemann
-
kahl@cas.mcmaster.ca
-
Reid Barton
-
roconnor@theorem.ca
-
Sittampalam, Ganesh
-
Stefan Holdermans
-
Stephan Friedrichs
-
Sterling Clover
-
Twan van Laarhoven