Proposal: add 'equating' function to Data.List

Hi, A common use case for 'on' (from Data.Function) is to use it with 'compare', e.g. 'compare `on` snd'. In fact, this pattern is so common that there's a convenient 'comparing' function which provides a shortcut for this use case such that one can write sortBy (comparing snd) instead of sortBy (compare `on` snd) I think another common use case is to use 'on' together with (==) as in groupBy ((==) `on` snd) In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==) such that one can write groupBy (equating snd) In fact, groupBy is just one of many *By functions taking an a -> a -> Bool -- many of which are Data.List, e.g. groupBy, nubBy, deleteBy, intersectBy, unionBy. Hence, it seems plausible to define 'equating' in Data.List. This is the same reasoning as why 'comparing' is in Data.Ord: because the module exposes a lot of *By functions taking an a -> a -> Ordering. - Frerich

Am 18.07.2014 21:26, schrieb Frerich Raabe:
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
I think it belongs to Data.Eq. I have already added it to my own Data.Eq module: http://hackage.haskell.org/package/utility-ht-0.0.10/docs/Data-Eq-HT.html this way I do not need to depend on a new GHC version in order to use it.

I am not super excited about library functions like comparing = (compare `on`) equating = ((==) `on`) It is rather knowledge how to use 'on', a programming pattern. The problem we have to solve is how we get a user searching for sortOn : Ord b => (a -> b) -> [a] -> [a] to find an explanation of the simple solution sortOn f = sortBy (compare `on` f) This problem of API explanation has been discussed on this list. Maybe instead of adding such simple functions to the library, one could put out a hoogle- and hayoo-indexed package that contains all such functions that could be expected to be in the library but are not since they have trivial implementations. Cheers, Andreas P.S.: In fact, `sortOn' would be more useful than `comparing' since it at least saves two words. On 18.07.2014 21:31, Henning Thielemann wrote:
Am 18.07.2014 21:26, schrieb Frerich Raabe:
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
I think it belongs to Data.Eq.
I have already added it to my own Data.Eq module:
http://hackage.haskell.org/package/utility-ht-0.0.10/docs/Data-Eq-HT.html
this way I do not need to depend on a new GHC version in order to use it.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
-- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel@gu.se http://www2.tcs.ifi.lmu.de/~abel/

I'm ever so slightly +1 on this proposal. Why? Because it gets reinvented every 4 months, and by just adding it we can stop having this discussion. I hereby proposed there exists a "co-Fairbairn threshold", the point at which the traffic caused by fighting against adding a commonly reinvented simple composition outweighs the pedagogical gain of pushing people to understand the simpler parts. That said, I'd prefer it live alongside comparing, and not get pushed redundantly around to other modules. -Edward
On Jul 18, 2014, at 5:11 PM, Andreas Abel
wrote: I am not super excited about library functions like
comparing = (compare `on`) equating = ((==) `on`)
It is rather knowledge how to use 'on', a programming pattern. The problem we have to solve is how we get a user searching for
sortOn : Ord b => (a -> b) -> [a] -> [a]
to find an explanation of the simple solution
sortOn f = sortBy (compare `on` f)
This problem of API explanation has been discussed on this list. Maybe instead of adding such simple functions to the library, one could put out a hoogle- and hayoo-indexed package that contains all such functions that could be expected to be in the library but are not since they have trivial implementations.
Cheers, Andreas
P.S.: In fact, `sortOn' would be more useful than `comparing' since it at least saves two words.
On 18.07.2014 21:31, Henning Thielemann wrote: Am 18.07.2014 21:26, schrieb Frerich Raabe:
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
I think it belongs to Data.Eq.
I have already added it to my own Data.Eq module:
http://hackage.haskell.org/package/utility-ht-0.0.10/docs/Data-Eq-HT.html
this way I do not need to depend on a new GHC version in order to use it.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se http://www2.tcs.ifi.lmu.de/~abel/ _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

I'm ever so slightly +1 on this proposal.
Why? Because it gets reinvented every 4 months, and by just adding it we can stop having this discussion.
I hereby proposed there exists a "co-Fairbairn threshold", the point at which the traffic caused by fighting against adding a commonly reinvented simple composition outweighs the pedagogical gain of pushing people to understand the simpler parts. OK, you have me convinced. You should put these thresholds of yours on
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 On 19/07/14 14:44, Edward Kmett wrote: the GHC Wiki or something. ;-)
That said, I'd prefer it live alongside comparing, and not get pushed redundantly around to other modules. I suggest: equating :: Eq a => (b -> a) -> b -> b -> Bool equating p x y = (p x) == (p y)
in Data.Eq, exposing it with module Data.Eq ( Eq(..), ) where If this sounds good I can write a patch for it, test it & upload it to phab to have it built & reviewed by austin and you. :-) - -- Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlPKaZ8ACgkQRtClrXBQc7WqgwEAgmlzkK+/JdsGDZ2OabyNPE8W y2zffqFTvus/GYO1S00BAKC3ncHM5R01sgrZfE8BhstzNNQ3JnTF5CoReBUedc4R =u6pc -----END PGP SIGNATURE-----

I didn't mean to preëmpt the whole discussion thread -- I'd rather let that play out, but I just wanted to express where my personal opinion lies on this matter. Data.Eq does sound like the right place for it, if we do go to put it in. -Edward
On Jul 19, 2014, at 8:50 AM, Alexander Berntsen
wrote: -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
On 19/07/14 14:44, Edward Kmett wrote: I'm ever so slightly +1 on this proposal.
Why? Because it gets reinvented every 4 months, and by just adding it we can stop having this discussion.
I hereby proposed there exists a "co-Fairbairn threshold", the point at which the traffic caused by fighting against adding a commonly reinvented simple composition outweighs the pedagogical gain of pushing people to understand the simpler parts. OK, you have me convinced. You should put these thresholds of yours on the GHC Wiki or something. ;-)
That said, I'd prefer it live alongside comparing, and not get pushed redundantly around to other modules. I suggest: equating :: Eq a => (b -> a) -> b -> b -> Bool equating p x y = (p x) == (p y)
in Data.Eq, exposing it with
module Data.Eq ( Eq(..), ) where
If this sounds good I can write a patch for it, test it & upload it to phab to have it built & reviewed by austin and you. :-) - -- Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/
iF4EAREIAAYFAlPKaZ8ACgkQRtClrXBQc7WqgwEAgmlzkK+/JdsGDZ2OabyNPE8W y2zffqFTvus/GYO1S00BAKC3ncHM5R01sgrZfE8BhstzNNQ3JnTF5CoReBUedc4R =u6pc -----END PGP SIGNATURE----- _______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 On 19/07/14 14:54, Edward Kmett wrote:
I didn't mean to preëmpt the whole discussion thread -- I'd rather let that play out, but I just wanted to express where my personal opinion lies on this matter. OK cool. I'm +1 now for what it's worth. :-]
Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlPKarsACgkQRtClrXBQc7WUNwD+LehOo+wr2OWLTEHA/Q+qa1nS ixmlPGzfaKIWBdRZa4MA/15iLuhblspfBXpzF1SAaNT5fr6kk1UwVbzZXaXMLNrT =pUoW -----END PGP SIGNATURE-----

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 On 19/07/14 14:44, Edward Kmett wrote: OK, you have me convinced. You should put these thresholds of yours on the GHC Wiki or something. ;-) I suggest: equating :: Eq a => (b -> a) -> b -> b -> Bool equating p x y = (p x) == (p y) in Data.Eq, exposing it with module Data.Eq ( Eq(..), ) where If this sounds good I can write a patch for it, test it & upload it to phab to have it built & reviewed by austin and you. :-) - -- Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlPKaaYACgkQRtClrXBQc7WyVQD8DjS2IDOakab786kWPP8CJZxU pAJDC90Fu4mtyOvYHGMA+wbKUBXSRgObToeJV0YJiYhWpXyTYw+InAJHRahApu3X =5zNd -----END PGP SIGNATURE-----

On 2014-07-18 23:11, Andreas Abel wrote:
I am not super excited about library functions like
comparing = (compare `on`) equating = ((==) `on`)
It is rather knowledge how to use 'on', a programming pattern.
I concur, but at the same time the argument given on this list by Robert Dockins' about seven years ago ( http://article.gmane.org/gmane.comp.lang.haskell.libraries/5622 ) seems compelling, too. Incidentally, the mail is form the thread in which the term Fairbairn threshold was coined. - Frerich

I think the `By` functions that expect a Bool are all cumbersome because
they are too flexible. 100% of the time I personally use these functions I
want to use Ord or Eq.
What I would like to see is a function groupOn next to groupBy.
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
Then equating is no longer needed, and one just writes: groupOn snd
I believe this style also gives better opportunity for optimization
(Scwartzian transform).
Of course, this function is still problematic because it operates only on
lists and does not group over the entire list, but those are separate
issues.
All of this is solved in mono-traversable right now by the groupAllOn
function [1]
[1]
http://hackage.haskell.org/package/mono-traversable-0.6.0.4/docs/Data-Sequen...
On Fri, Jul 18, 2014 at 12:26 PM, Frerich Raabe
Hi,
A common use case for 'on' (from Data.Function) is to use it with 'compare', e.g. 'compare `on` snd'. In fact, this pattern is so common that there's a convenient 'comparing' function which provides a shortcut for this use case such that one can write
sortBy (comparing snd)
instead of
sortBy (compare `on` snd)
I think another common use case is to use 'on' together with (==) as in
groupBy ((==) `on` snd)
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
In fact, groupBy is just one of many *By functions taking an a -> a -> Bool -- many of which are Data.List, e.g. groupBy, nubBy, deleteBy, intersectBy, unionBy. Hence, it seems plausible to define 'equating' in Data.List. This is the same reasoning as why 'comparing' is in Data.Ord: because the module exposes a lot of *By functions taking an a -> a -> Ordering.
- Frerich
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Am 18.07.2014 21:57, schrieb Greg Weber:
I think the `By` functions that expect a Bool are all cumbersome because they are too flexible. 100% of the time I personally use these functions I want to use Ord or Eq. What I would like to see is a function groupOn next to groupBy.
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
Then equating is no longer needed, and one just writes: groupOn snd I believe this style also gives better opportunity for optimization (Scwartzian transform).
It's also in my utility package: http://hackage.haskell.org/package/utility-ht-0.0.10/docs/Data-List-Key.html I have also a version of 'groupBy' that returns a list of non-empty lists: http://hackage.haskell.org/package/non-empty-0.2/docs/Data-NonEmpty-Mixed.ht... It's all Haskell 98.

On Fri, Jul 18, 2014 at 1:07 PM, Henning Thielemann < schlepptop@henning-thielemann.de> wrote:
Am 18.07.2014 21:57, schrieb Greg Weber:
I think the `By` functions that expect a Bool are all cumbersome because
they are too flexible. 100% of the time I personally use these functions I want to use Ord or Eq. What I would like to see is a function groupOn next to groupBy.
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
Then equating is no longer needed, and one just writes: groupOn snd I believe this style also gives better opportunity for optimization (Scwartzian transform).
It's also in my utility package:
http://hackage.haskell.org/package/utility-ht-0.0.10/ docs/Data-List-Key.html
I have also a version of 'groupBy' that returns a list of non-empty lists:
http://hackage.haskell.org/package/non-empty-0.2/docs/ Data-NonEmpty-Mixed.html#v:groupBy
non-empty looks nice! semigroups has groupBy1 now that returns NonEmpty http://hackage.haskell.org/package/semigroups-0.15.1/docs/Data-List-NonEmpty... It's all Haskell 98.
You should add mono-traversable (Data.MinLen) [1] to your compariisons. It should be a lot more efficient when tracking length beyond 1 element, but it is definitely not Haskell 98. [1] http://hackage.haskell.org/package/mono-traversable-0.6.0.4/docs/Data-MinLen...

I am -1 on things that encourage converting Eq to Bool rather than just
using Eq directly.
Is there a use case for group that is not satisfied by groupOn with a
newtype with an Eq instance?
Granted, a newtype may be heavy-weight, but I feel that the current group
should be an escape hatch in the rare case that groupOn does not suffice,
not something we codify via Fairbairn threshold because that is the only
API that exists today. I can create a separate proposal for adding groupOn,
etc.
On Fri, Jul 18, 2014 at 12:57 PM, Greg Weber
I think the `By` functions that expect a Bool are all cumbersome because they are too flexible. 100% of the time I personally use these functions I want to use Ord or Eq. What I would like to see is a function groupOn next to groupBy.
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
Then equating is no longer needed, and one just writes: groupOn snd I believe this style also gives better opportunity for optimization (Scwartzian transform).
Of course, this function is still problematic because it operates only on lists and does not group over the entire list, but those are separate issues. All of this is solved in mono-traversable right now by the groupAllOn function [1]
[1] http://hackage.haskell.org/package/mono-traversable-0.6.0.4/docs/Data-Sequen...
On Fri, Jul 18, 2014 at 12:26 PM, Frerich Raabe
wrote: Hi,
A common use case for 'on' (from Data.Function) is to use it with 'compare', e.g. 'compare `on` snd'. In fact, this pattern is so common that there's a convenient 'comparing' function which provides a shortcut for this use case such that one can write
sortBy (comparing snd)
instead of
sortBy (compare `on` snd)
I think another common use case is to use 'on' together with (==) as in
groupBy ((==) `on` snd)
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
In fact, groupBy is just one of many *By functions taking an a -> a -> Bool -- many of which are Data.List, e.g. groupBy, nubBy, deleteBy, intersectBy, unionBy. Hence, it seems plausible to define 'equating' in Data.List. This is the same reasoning as why 'comparing' is in Data.Ord: because the module exposes a lot of *By functions taking an a -> a -> Ordering.
- Frerich
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

The utility of the proposed "equating" extends far beyond simply using it
with groupBy. Just last week I used "on (==)" as part of a complicated
boolean expression.
That said, I just want to be clear that I'm understanding Greg properly.
Are you advocating that one should generally create a newtype+Eq instance
rather than using "on (==)"? What is the benefit of this approach? The
only one I can think of is that it makes the standard libraries smaller,
which seems like a rather small gain considering that you've changed a
7-character expression into multi-line boilerplate for everyone, hampering
readability in the process. Is there something I'm missing here?
(Currently +0 on the proposal)
John L.
On Mon, Jul 21, 2014 at 8:27 AM, Greg Weber
I am -1 on things that encourage converting Eq to Bool rather than just using Eq directly.
Is there a use case for group that is not satisfied by groupOn with a newtype with an Eq instance? Granted, a newtype may be heavy-weight, but I feel that the current group should be an escape hatch in the rare case that groupOn does not suffice, not something we codify via Fairbairn threshold because that is the only API that exists today. I can create a separate proposal for adding groupOn, etc.
On Fri, Jul 18, 2014 at 12:57 PM, Greg Weber
wrote: I think the `By` functions that expect a Bool are all cumbersome because they are too flexible. 100% of the time I personally use these functions I want to use Ord or Eq. What I would like to see is a function groupOn next to groupBy.
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
Then equating is no longer needed, and one just writes: groupOn snd I believe this style also gives better opportunity for optimization (Scwartzian transform).
Of course, this function is still problematic because it operates only on lists and does not group over the entire list, but those are separate issues. All of this is solved in mono-traversable right now by the groupAllOn function [1]
[1] http://hackage.haskell.org/package/mono-traversable-0.6.0.4/docs/Data-Sequen...
On Fri, Jul 18, 2014 at 12:26 PM, Frerich Raabe
wrote: Hi,
A common use case for 'on' (from Data.Function) is to use it with 'compare', e.g. 'compare `on` snd'. In fact, this pattern is so common that there's a convenient 'comparing' function which provides a shortcut for this use case such that one can write
sortBy (comparing snd)
instead of
sortBy (compare `on` snd)
I think another common use case is to use 'on' together with (==) as in
groupBy ((==) `on` snd)
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
In fact, groupBy is just one of many *By functions taking an a -> a -> Bool -- many of which are Data.List, e.g. groupBy, nubBy, deleteBy, intersectBy, unionBy. Hence, it seems plausible to define 'equating' in Data.List. This is the same reasoning as why 'comparing' is in Data.Ord: because the module exposes a lot of *By functions taking an a -> a -> Ordering.
- Frerich
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

Eq instances should only be used for conceptual equality, and never just
for convenience applying some function or other. I don't think that makes
any sort of argument for "equating", though.
On Jul 20, 2014 8:46 PM, "John Lato"
The utility of the proposed "equating" extends far beyond simply using it with groupBy. Just last week I used "on (==)" as part of a complicated boolean expression.
That said, I just want to be clear that I'm understanding Greg properly. Are you advocating that one should generally create a newtype+Eq instance rather than using "on (==)"? What is the benefit of this approach? The only one I can think of is that it makes the standard libraries smaller, which seems like a rather small gain considering that you've changed a 7-character expression into multi-line boilerplate for everyone, hampering readability in the process. Is there something I'm missing here?
(Currently +0 on the proposal)
John L.
On Mon, Jul 21, 2014 at 8:27 AM, Greg Weber
wrote: I am -1 on things that encourage converting Eq to Bool rather than just using Eq directly.
Is there a use case for group that is not satisfied by groupOn with a newtype with an Eq instance? Granted, a newtype may be heavy-weight, but I feel that the current group should be an escape hatch in the rare case that groupOn does not suffice, not something we codify via Fairbairn threshold because that is the only API that exists today. I can create a separate proposal for adding groupOn, etc.
On Fri, Jul 18, 2014 at 12:57 PM, Greg Weber
wrote: I think the `By` functions that expect a Bool are all cumbersome because they are too flexible. 100% of the time I personally use these functions I want to use Ord or Eq. What I would like to see is a function groupOn next to groupBy.
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
Then equating is no longer needed, and one just writes: groupOn snd I believe this style also gives better opportunity for optimization (Scwartzian transform).
Of course, this function is still problematic because it operates only on lists and does not group over the entire list, but those are separate issues. All of this is solved in mono-traversable right now by the groupAllOn function [1]
[1] http://hackage.haskell.org/package/mono-traversable-0.6.0.4/docs/Data-Sequen...
On Fri, Jul 18, 2014 at 12:26 PM, Frerich Raabe
wrote: Hi,
A common use case for 'on' (from Data.Function) is to use it with 'compare', e.g. 'compare `on` snd'. In fact, this pattern is so common that there's a convenient 'comparing' function which provides a shortcut for this use case such that one can write
sortBy (comparing snd)
instead of
sortBy (compare `on` snd)
I think another common use case is to use 'on' together with (==) as in
groupBy ((==) `on` snd)
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
In fact, groupBy is just one of many *By functions taking an a -> a -> Bool -- many of which are Data.List, e.g. groupBy, nubBy, deleteBy, intersectBy, unionBy. Hence, it seems plausible to define 'equating' in Data.List. This is the same reasoning as why 'comparing' is in Data.Ord: because the module exposes a lot of *By functions taking an a -> a -> Ordering.
- Frerich
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Sun, Jul 20, 2014 at 5:46 PM, John Lato
The utility of the proposed "equating" extends far beyond simply using it with groupBy. Just last week I used "on (==)" as part of a complicated boolean expression.
That said, I just want to be clear that I'm understanding Greg properly. Are you advocating that one should generally create a newtype+Eq instance rather than using "on (==)"? What is the benefit of this approach? The only one I can think of is that it makes the standard libraries smaller, which seems like a rather small gain considering that you've changed a 7-character expression into multi-line boilerplate for everyone, hampering readability in the process. Is there something I'm missing here?
Sorry I didn't do a good job explaining. groupOn takes a function that is a projection to an equality instance (Eq b => (a -> b)). So there is no need for a newtype, and this interface has suited 100% of my needs, and every usage I have ever seen in Haskell code. My presumption is that the only reason this interface is not 100% satisfactory and we have this weird interface based on Bool is because you may want to compare something that does not have an Eq instance. One could still handle that case by wrapping the projected value in a newtype and writing an Eq instance for that newtype.
(Currently +0 on the proposal)
John L.
On Mon, Jul 21, 2014 at 8:27 AM, Greg Weber
wrote: I am -1 on things that encourage converting Eq to Bool rather than just using Eq directly.
Is there a use case for group that is not satisfied by groupOn with a newtype with an Eq instance? Granted, a newtype may be heavy-weight, but I feel that the current group should be an escape hatch in the rare case that groupOn does not suffice, not something we codify via Fairbairn threshold because that is the only API that exists today. I can create a separate proposal for adding groupOn, etc.
On Fri, Jul 18, 2014 at 12:57 PM, Greg Weber
wrote: I think the `By` functions that expect a Bool are all cumbersome because they are too flexible. 100% of the time I personally use these functions I want to use Ord or Eq. What I would like to see is a function groupOn next to groupBy.
groupOn :: Eq b => (a -> b) -> [a] -> [[a]]
Then equating is no longer needed, and one just writes: groupOn snd I believe this style also gives better opportunity for optimization (Scwartzian transform).
Of course, this function is still problematic because it operates only on lists and does not group over the entire list, but those are separate issues. All of this is solved in mono-traversable right now by the groupAllOn function [1]
[1] http://hackage.haskell.org/package/mono-traversable-0.6.0.4/docs/Data-Sequen...
On Fri, Jul 18, 2014 at 12:26 PM, Frerich Raabe
wrote: Hi,
A common use case for 'on' (from Data.Function) is to use it with 'compare', e.g. 'compare `on` snd'. In fact, this pattern is so common that there's a convenient 'comparing' function which provides a shortcut for this use case such that one can write
sortBy (comparing snd)
instead of
sortBy (compare `on` snd)
I think another common use case is to use 'on' together with (==) as in
groupBy ((==) `on` snd)
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
In fact, groupBy is just one of many *By functions taking an a -> a -> Bool -- many of which are Data.List, e.g. groupBy, nubBy, deleteBy, intersectBy, unionBy. Hence, it seems plausible to define 'equating' in Data.List. This is the same reasoning as why 'comparing' is in Data.Ord: because the module exposes a lot of *By functions taking an a -> a -> Ordering.
- Frerich
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

On Mon, Jul 21, 2014 at 9:38 AM, Greg Weber
On Sun, Jul 20, 2014 at 5:46 PM, John Lato
wrote: The utility of the proposed "equating" extends far beyond simply using it with groupBy. Just last week I used "on (==)" as part of a complicated boolean expression.
That said, I just want to be clear that I'm understanding Greg properly. Are you advocating that one should generally create a newtype+Eq instance rather than using "on (==)"? What is the benefit of this approach? The only one I can think of is that it makes the standard libraries smaller, which seems like a rather small gain considering that you've changed a 7-character expression into multi-line boilerplate for everyone, hampering readability in the process. Is there something I'm missing here?
Sorry I didn't do a good job explaining. groupOn takes a function that is a projection to an equality instance (Eq b => (a -> b)). So there is no need for a newtype, and this interface has suited 100% of my needs, and every usage I have ever seen in Haskell code.
My presumption is that the only reason this interface is not 100% satisfactory and we have this weird interface based on Bool is because you may want to compare something that does not have an Eq instance. One could still handle that case by wrapping the projected value in a newtype and writing an Eq instance for that newtype.
I see, thanks for the explanation. Seems like a reasonable function IMHO. It still isn't a full replacement for equating though. In my case, I used "if on (==) someLongSelector a b then ..." to save some characters over the obvious alternative.

What I'd like for Data.List is uncons :: [a] -> Maybe (a, [a]). uncons [] = Nothing uncons (a:as) = Just (a,as) I believe Data.Text and maybe even Data.ByteString have similar functions. The main reason, I think: The idiom do x <- listToMaybe xss ... ... tail xss ... is a bit ugly as the safety of tail xs depends implicitly on the fact that listToMaybe guards it, and because it treats the head and tail completely differently. Far prettier: do (x,xs) <- uncons xss ...

Am 18.07.2014 23:19, schrieb David Feuer:
What I'd like for Data.List is
uncons :: [a] -> Maybe (a, [a]). uncons [] = Nothing uncons (a:as) = Just (a,as)
I believe Data.Text and maybe even Data.ByteString have similar functions.
I called it viewL, analogously to Data.Sequence: http://hackage.haskell.org/package/utility-ht-0.0.10/docs/Data-List-HT.html#...

Put in a separate proposal for Data.List.uncons. It is a reasonable, self-contained function that encourages good style. The name has been commonly used and reinvented over and over and as a top level proposal we can have any bikeshedding discussion without derailing this one. I honestly thought it was already in there. -Edward
On Jul 18, 2014, at 5:19 PM, David Feuer
wrote: What I'd like for Data.List is
uncons :: [a] -> Maybe (a, [a]). uncons [] = Nothing uncons (a:as) = Just (a,as)
I believe Data.Text and maybe even Data.ByteString have similar functions. The main reason, I think:
The idiom
do x <- listToMaybe xss ... ... tail xss ...
is a bit ugly as the safety of tail xs depends implicitly on the fact that listToMaybe guards it, and because it treats the head and tail completely differently. Far prettier:
do (x,xs) <- uncons xss ...
_______________________________________________ Libraries mailing list Libraries@haskell.org http://www.haskell.org/mailman/listinfo/libraries

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 - -1 because I'm not convinced this belongs in Data.List. comparing is in Data.Ord and is: Data.Ord comparing :: Ord a => (b -> a) -> b -> b -> Ordering So equating should be in Data.Eq, with: equating :: Eq a => (b -> a) -> b -> b -> Bool Furthermore I do not like your definition, and would prefer: equating p x y = (p x) == (p y) With these issues amended, I'm 0 on the proposal. - -- Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlPKToAACgkQRtClrXBQc7X59AD9GjgcSZnFPxMY1jJLt5KFP/PI /StXr9g6igtoFqTigJ8BALGhPgy63dY1jXoKxrUoGaS9FgRX6ZM7SklGsDiEKn7h =usCs -----END PGP SIGNATURE-----

On 19 July 2014 20:54, Alexander Berntsen
Furthermore I do not like your definition, and would prefer:
equating p x y = (p x) == (p y)
How is this any different from the original proposed solution? Either way, it's -1 for the proposal from me as well. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 On 19/07/14 13:44, Ivan Lazar Miljenovic wrote:
equating p x y = (p x) == (p y) How is this any different from the original proposed solution? I'm not sure what you mean. Is it not obvious? The original proposal is defined in terms of on. Mine is not.
- -- Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlPKYX4ACgkQRtClrXBQc7WUyQD9EuL/D3sOlpa8ZqWTF7URRTfX fMVGqDLu0K/MdZL4sKoBAImJQ5rjR2aHWNKAHfKEIW2rLe0QDKmOjQcSVGyCEjYG =6bur -----END PGP SIGNATURE-----

On 19 July 2014 22:15, Alexander Berntsen
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256
On 19/07/14 13:44, Ivan Lazar Miljenovic wrote:
equating p x y = (p x) == (p y) How is this any different from the original proposed solution? I'm not sure what you mean. Is it not obvious? The original proposal is defined in terms of on. Mine is not.
I meant more along the lines of why is this any better than using on. -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 On 19/07/14 15:52, Ivan Lazar Miljenovic wrote:
I meant more along the lines of why is this any better than using on. Ah, I see. To avoid importing 'on' into 'Data.Eq'. and because it is symmetrical with how 'comparing' is already defined in 'Data.Ord'.
Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlPKeKkACgkQRtClrXBQc7UbMAD9HKf+TktrC0P7I8iqodzXsOjy gGYOXpYnQbFW6uVJW9YBAJuBjUonYPfO6OaIOulM8DeWZGOlFx+cW0TQXGM/wBt1 =kayu -----END PGP SIGNATURE-----

On 2014-07-18 21:26, Frerich Raabe wrote:
In a similiar vein as with 'comparing', I think it would be nice if there was a function which encapsulates this use case, like
equating :: Eq b => (a -> b) -> a -> a -> Bool equating = on (==)
such that one can write
groupBy (equating snd)
I don't know whether this is relevant to the decision making process, but it appears there's some precedence already in the 'basic-prelude' package by Dan Burton and Michael Snoyman: the 'CorePrelude' module exposes an 'equating' function: https://hackage.haskell.org/package/basic-prelude-0.3.8/docs/CorePrelude.htm... - Frerich

On 2014-07-18 at 21:26:16 +0200, Frerich Raabe wrote: [...]
In fact, this pattern is so common that there's a convenient 'comparing' function which provides a shortcut for this use case
btw, you got the history/causality backwards in your argument: afaik, 'comparing' predates 'on', and removing the existing function 'comparing' would have been a backward incompatible change. [...]
In fact, groupBy is just one of many *By functions taking an a -> a -> Bool -- many of which are Data.List, e.g. groupBy, nubBy, deleteBy, intersectBy, unionBy. Hence, it seems plausible to define 'equating' in Data.List.
This is the same reasoning as why 'comparing' is in Data.Ord: because the module exposes a lot of *By functions taking an a -> a -> Ordering.
I don't see in what way 'equating' belonging in "Data.List" poses the "the same reasoning" of 'comparing' being in "Data.Ord". This would rather call for 'equating' belonging in "Data.Eq" (which is actually a module that's almost never imported explicitly). Consequently, I'm -1 on adding 'equating' to Data.List. However, I'm generally -0.5 on adding 'equating', as I'm not convinced 'equating' provides any significant benefit over "on (==)" (whose only downside to me is that it requires an additional "import Data.Function") I'd rather improve the existing documentation in Data.List to provide code examples involving the use of `on` for the most common tasks. Cheers, hvr

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 On 20/07/14 23:25, Herbert Valerio Riedel wrote:
I'm not convinced 'equating' provides any significant benefit over "on (==)" It doesn't.
Thus my initial gut reaction of +0. But I agree with Edward's proposed co-fairbairn threshold, putting me at +1. - -- Alexander alexander@plaimi.net https://secure.plaimi.net/~alexander -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iF4EAREIAAYFAlPMORUACgkQRtClrXBQc7V9BgD9HPKP7Sv3fYsbJlpWy7y7CQPB f9hlCvYEOk0waQAYd48BAIhnQwxJv9UdfDNXVkQoB+YDdTq87+DBHtXp6SKULP+l =LbvI -----END PGP SIGNATURE-----

I'm -1 on adding equating to base. I don't think it improves over using `on` or even just a locally defined function or lambda and just adds another name to learn. If we do have it I'm also against it going into Data.List, and I would prefer Data.Eq. I'm quite happy to have this proposal come up again in a few months and direct that discussion back to the archive.
participants (11)
-
Alexander Berntsen
-
Andreas Abel
-
David Feuer
-
Edward Kmett
-
Eric Mertens
-
Frerich Raabe
-
Greg Weber
-
Henning Thielemann
-
Herbert Valerio Riedel
-
Ivan Lazar Miljenovic
-
John Lato