From merijn at inconsistent.nl Tue Oct 10 09:29:05 2017 From: merijn at inconsistent.nl (Merijn Verstraaten) Date: Tue, 10 Oct 2017 11:29:05 +0200 Subject: Proposal: Taking over/up network maintainership Message-ID: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> Hi hackage admins & libraries@ readers, So, to the best of my knowledge 'network' is currently maintained by libraries@/the community, which is code for "not maintained". I've previously entertained the thought of taking up maintainership, but so far was held back by the fact that I don't do windows dev experience. I've discussed this in #ghc before and the consensus was that *nix only maintenance is probably still better than no maintenance. I was inspired to finally write this email and try to take up maintenance after spending all day yesterday tomorrow debugging an issue in my code, only to realise that Network.ByteString.Lazy.getContents will literally *always* crash/throw an exception when used. My plans are to: Short term: fix obvious errors like getContents, cut through the PR backlog on github to see what can be merged, what needs work, etc. Medium term: Improve exception/error handling (network specific exception type that people can catch), better (async) exceptions safety guarantees/documentation of safety Long term: I would like ditch the current (deprecated) high-level interface and replace it with modern high level API. Now, the biggest problem is that I don't have experience developing on Windows and neither the time nor the motivation to get started with that, so I will need someone to take up co-maintainership of the windows parts (I'll probably send an email about this to -cafe if people are supportive of me taking up maintenance). Cheers, Merijn -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 874 bytes Desc: Message signed with OpenPGP URL: From danburton.email at gmail.com Tue Oct 10 13:51:08 2017 From: danburton.email at gmail.com (Dan Burton) Date: Tue, 10 Oct 2017 06:51:08 -0700 Subject: Proposal: Taking over/up network maintainership In-Reply-To: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> References: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> Message-ID: If the long term goal is to completely revamp the api, why not just write a new library? On Oct 10, 2017 04:29, "Merijn Verstraaten" wrote: > Hi hackage admins & libraries@ readers, > > So, to the best of my knowledge 'network' is currently maintained by > libraries@/the community, which is code for "not maintained". I've > previously entertained the thought of taking up maintainership, but so far > was held back by the fact that I don't do windows dev experience. I've > discussed this in #ghc before and the consensus was that *nix only > maintenance is probably still better than no maintenance. > > I was inspired to finally write this email and try to take up maintenance > after spending all day yesterday tomorrow debugging an issue in my code, > only to realise that Network.ByteString.Lazy.getContents will literally > *always* crash/throw an exception when used. > > My plans are to: > Short term: fix obvious errors like getContents, cut through the PR > backlog on github to see what can be merged, what needs work, etc. > > Medium term: Improve exception/error handling (network specific exception > type that people can catch), better (async) exceptions safety > guarantees/documentation of safety > > Long term: I would like ditch the current (deprecated) high-level > interface and replace it with modern high level API. > > Now, the biggest problem is that I don't have experience developing on > Windows and neither the time nor the motivation to get started with that, > so I will need someone to take up co-maintainership of the windows parts > (I'll probably send an email about this to -cafe if people are supportive > of me taking up maintenance). > > Cheers, > Merijn > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From merijn at inconsistent.nl Tue Oct 10 14:36:11 2017 From: merijn at inconsistent.nl (Merijn Verstraaten) Date: Tue, 10 Oct 2017 16:36:11 +0200 Subject: Proposal: Taking over/up network maintainership In-Reply-To: References: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> Message-ID: <6AA87853-7C9A-427A-BD77-3DFC848B2C5B@inconsistent.nl> Hi Dan, The long term goal is not to revamp the entire API of network, just the high-level interface in the Network module. Currently (actually, for the entire past, like, 5 years I've been using network), the documentation of the Network module has stated: "This module is kept for backwards-compatibility. New users are encouraged to use Network.Socket instead. Network was intended as a "higher-level" interface to networking facilities, and only supports TCP." Why keep around a deprecated high-level interface and recommend people use the low level one. Seems much better (long-term) to overhaul the high-level interface in Network so that it actually becomes recommend over writing code using Network.Socket itself. Cheers, Merijn > On 10 Oct 2017, at 15:51, Dan Burton wrote: > > If the long term goal is to completely revamp the api, why not just write a new library? > > On Oct 10, 2017 04:29, "Merijn Verstraaten" wrote: > Hi hackage admins & libraries@ readers, > > So, to the best of my knowledge 'network' is currently maintained by libraries@/the community, which is code for "not maintained". I've previously entertained the thought of taking up maintainership, but so far was held back by the fact that I don't do windows dev experience. I've discussed this in #ghc before and the consensus was that *nix only maintenance is probably still better than no maintenance. > > I was inspired to finally write this email and try to take up maintenance after spending all day yesterday tomorrow debugging an issue in my code, only to realise that Network.ByteString.Lazy.getContents will literally *always* crash/throw an exception when used. > > My plans are to: > Short term: fix obvious errors like getContents, cut through the PR backlog on github to see what can be merged, what needs work, etc. > > Medium term: Improve exception/error handling (network specific exception type that people can catch), better (async) exceptions safety guarantees/documentation of safety > > Long term: I would like ditch the current (deprecated) high-level interface and replace it with modern high level API. > > Now, the biggest problem is that I don't have experience developing on Windows and neither the time nor the motivation to get started with that, so I will need someone to take up co-maintainership of the windows parts (I'll probably send an email about this to -cafe if people are supportive of me taking up maintenance). > > Cheers, > Merijn > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 874 bytes Desc: Message signed with OpenPGP URL: From michael at snoyman.com Tue Oct 10 14:53:58 2017 From: michael at snoyman.com (Michael Snoyman) Date: Tue, 10 Oct 2017 17:53:58 +0300 Subject: Proposal: Taking over/up network maintainership In-Reply-To: <6AA87853-7C9A-427A-BD77-3DFC848B2C5B@inconsistent.nl> References: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> <6AA87853-7C9A-427A-BD77-3DFC848B2C5B@inconsistent.nl> Message-ID: > Why keep around a deprecated high-level interface and recommend people use the low level one. How about a third option: deprecate the old high-level interface, and add a new, better designed high-level interface? That way you keep backwards compatibility for existing code, while allowing a new API to come into existence. Personally, in these kinds of situations, I usually recommend starting the new API off in a separate package to allow for more rapid API iteration without inflicting breaking API changes on the original package, and then—once the API has stabilized—consider including it in the original package. Michael On Tue, Oct 10, 2017 at 5:36 PM, Merijn Verstraaten wrote: > Hi Dan, > > The long term goal is not to revamp the entire API of network, just the > high-level interface in the Network module. Currently (actually, for the > entire past, like, 5 years I've been using network), the documentation of > the Network module has stated: > > "This module is kept for backwards-compatibility. New users are encouraged > to use Network.Socket instead. > > Network was intended as a "higher-level" interface to networking > facilities, and only supports TCP." > > Why keep around a deprecated high-level interface and recommend people use > the low level one. Seems much better (long-term) to overhaul the high-level > interface in Network so that it actually becomes recommend over writing > code using Network.Socket itself. > > Cheers, > Merijn > > > On 10 Oct 2017, at 15:51, Dan Burton wrote: > > > > If the long term goal is to completely revamp the api, why not just > write a new library? > > > > On Oct 10, 2017 04:29, "Merijn Verstraaten" > wrote: > > Hi hackage admins & libraries@ readers, > > > > So, to the best of my knowledge 'network' is currently maintained by > libraries@/the community, which is code for "not maintained". I've > previously entertained the thought of taking up maintainership, but so far > was held back by the fact that I don't do windows dev experience. I've > discussed this in #ghc before and the consensus was that *nix only > maintenance is probably still better than no maintenance. > > > > I was inspired to finally write this email and try to take up > maintenance after spending all day yesterday tomorrow debugging an issue in > my code, only to realise that Network.ByteString.Lazy.getContents will > literally *always* crash/throw an exception when used. > > > > My plans are to: > > Short term: fix obvious errors like getContents, cut through the PR > backlog on github to see what can be merged, what needs work, etc. > > > > Medium term: Improve exception/error handling (network specific > exception type that people can catch), better (async) exceptions safety > guarantees/documentation of safety > > > > Long term: I would like ditch the current (deprecated) high-level > interface and replace it with modern high level API. > > > > Now, the biggest problem is that I don't have experience developing on > Windows and neither the time nor the motivation to get started with that, > so I will need someone to take up co-maintainership of the windows parts > (I'll probably send an email about this to -cafe if people are supportive > of me taking up maintenance). > > > > Cheers, > > Merijn > > > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From merijn at inconsistent.nl Tue Oct 10 15:51:46 2017 From: merijn at inconsistent.nl (Merijn Verstraaten) Date: Tue, 10 Oct 2017 17:51:46 +0200 Subject: Proposal: Taking over/up network maintainership In-Reply-To: References: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> <6AA87853-7C9A-427A-BD77-3DFC848B2C5B@inconsistent.nl> Message-ID: On 10 Oct 2017, at 16:53, Michael Snoyman wrote: > > Why keep around a deprecated high-level interface and recommend people use the low level one. > > How about a third option: deprecate the old high-level interface, and add a new, better designed high-level interface? That way you keep backwards compatibility for existing code, while allowing a new API to come into existence. > > Personally, in these kinds of situations, I usually recommend starting the new API off in a separate package to allow for more rapid API iteration without inflicting breaking API changes on the original package, and then—once the API has stabilized—consider including it in the original package. Honestly, I don't have any strong opinions on this yet. "long-term" goal can just easily be read as "wishful thinking" in the original email. I don't have any concrete plans, so for now it's mostly about "stop things being broken". Starting a new package/forking network for fast iteration is a nice idea and all, but just leaves everyone else with a broken network package atm. I was actually doubting whether I should even talk about "long term" plans, clearly it was a mistake to include that. I don't want this turning in an abstract bike shedding discussion about potential future plans. Cheers, Merijn -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 874 bytes Desc: Message signed with OpenPGP URL: From david.feuer at gmail.com Tue Oct 10 16:20:27 2017 From: david.feuer at gmail.com (David Feuer) Date: Tue, 10 Oct 2017 12:20:27 -0400 Subject: Proposal: Taking over/up network maintainership In-Reply-To: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> References: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> Message-ID: A maintainer has arrived, and we should all rejoice! Is a proposal even necessary? Regardless, Merijn is obviously qualified, and the package obviously needs a maintainer, so +1. On Oct 10, 2017 5:29 AM, "Merijn Verstraaten" wrote: > Hi hackage admins & libraries@ readers, > > So, to the best of my knowledge 'network' is currently maintained by > libraries@/the community, which is code for "not maintained". I've > previously entertained the thought of taking up maintainership, but so far > was held back by the fact that I don't do windows dev experience. I've > discussed this in #ghc before and the consensus was that *nix only > maintenance is probably still better than no maintenance. > > I was inspired to finally write this email and try to take up maintenance > after spending all day yesterday tomorrow debugging an issue in my code, > only to realise that Network.ByteString.Lazy.getContents will literally > *always* crash/throw an exception when used. > > My plans are to: > Short term: fix obvious errors like getContents, cut through the PR > backlog on github to see what can be merged, what needs work, etc. > > Medium term: Improve exception/error handling (network specific exception > type that people can catch), better (async) exceptions safety > guarantees/documentation of safety > > Long term: I would like ditch the current (deprecated) high-level > interface and replace it with modern high level API. > > Now, the biggest problem is that I don't have experience developing on > Windows and neither the time nor the motivation to get started with that, > so I will need someone to take up co-maintainership of the windows parts > (I'll probably send an email about this to -cafe if people are supportive > of me taking up maintenance). > > Cheers, > Merijn > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From evan at evanrutledgeborden.dreamhosters.com Thu Oct 12 02:05:23 2017 From: evan at evanrutledgeborden.dreamhosters.com (evan@evan-borden.com) Date: Wed, 11 Oct 2017 22:05:23 -0400 Subject: Proposal: Taking over/up network maintainership In-Reply-To: References: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> Message-ID: Kazu and I have been mostly derelict in our duties aside from critical bugs and base conflicts on new versions. +1 from me, but I would advise a strong preference towards backwards compatibly. Network is at the bottom of many stacks and breaking changes bubble far. On Oct 10, 2017 12:21 PM, "David Feuer" wrote: > A maintainer has arrived, and we should all rejoice! Is a proposal even > necessary? Regardless, Merijn is obviously qualified, and the package > obviously needs a maintainer, so +1. > > On Oct 10, 2017 5:29 AM, "Merijn Verstraaten" > wrote: > >> Hi hackage admins & libraries@ readers, >> >> So, to the best of my knowledge 'network' is currently maintained by >> libraries@/the community, which is code for "not maintained". I've >> previously entertained the thought of taking up maintainership, but so far >> was held back by the fact that I don't do windows dev experience. I've >> discussed this in #ghc before and the consensus was that *nix only >> maintenance is probably still better than no maintenance. >> >> I was inspired to finally write this email and try to take up maintenance >> after spending all day yesterday tomorrow debugging an issue in my code, >> only to realise that Network.ByteString.Lazy.getContents will literally >> *always* crash/throw an exception when used. >> >> My plans are to: >> Short term: fix obvious errors like getContents, cut through the PR >> backlog on github to see what can be merged, what needs work, etc. >> >> Medium term: Improve exception/error handling (network specific exception >> type that people can catch), better (async) exceptions safety >> guarantees/documentation of safety >> >> Long term: I would like ditch the current (deprecated) high-level >> interface and replace it with modern high level API. >> >> Now, the biggest problem is that I don't have experience developing on >> Windows and neither the time nor the motivation to get started with that, >> so I will need someone to take up co-maintainership of the windows parts >> (I'll probably send an email about this to -cafe if people are supportive >> of me taking up maintenance). >> >> Cheers, >> Merijn >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From kazu at iij.ad.jp Thu Oct 12 04:00:17 2017 From: kazu at iij.ad.jp (Kazu Yamamoto (=?iso-2022-jp?B?GyRCOzNLXE9CSScbKEI=?=)) Date: Thu, 12 Oct 2017 13:00:17 +0900 (JST) Subject: Proposal: Taking over/up network maintainership In-Reply-To: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> References: <5080B1CE-92FA-41AF-9859-6036EE831761@inconsistent.nl> Message-ID: <20171012.130017.1588326563536359214.kazu@iij.ad.jp> Hello Merijn, > So, to the best of my knowledge 'network' is currently maintained by > libraries@/the community, which is code for "not maintained". I've > previously entertained the thought of taking up maintainership, but so > far was held back by the fact that I don't do windows dev > experience. I've discussed this in #ghc before and the consensus was > that *nix only maintenance is probably still better than no > maintenance. As Evan explained, Evan and I are the maintainers. But our activities are limited to bug fixes, documentation updates and catch-up to new GHCs. I welcome you to be a maintainer. I think we need a guideline for contributions. hs-tls is doing this very well. See: https://github.com/vincenthz/hs-tls/blob/master/CONTRIBUTING.md The contributors of hs-tls review others' PRs and its history stays linear. It's really nice. > My plans are to: > Short term: fix obvious errors like getContents, cut through the PR > backlog on github to see what can be merged, what needs work, etc. > > Medium term: Improve exception/error handling (network specific > exception type that people can catch), better (async) exceptions > safety guarantees/documentation of safety > > Long term: I would like ditch the current (deprecated) high-level > interface and replace it with modern high level API. > > Now, the biggest problem is that I don't have experience developing on > Windows and neither the time nor the motivation to get started with > that, so I will need someone to take up co-maintainership of the > windows parts (I'll probably send an email about this to -cafe if > people are supportive of me taking up maintenance). Evan and I don't have milestones for new features. If you want to develop the network library aggressively, please create milestones on github so that contributors can understand what you are trying to do. As Evan said, the backward compatibility is important for this library. And I would support Michael's idea: "deprecate the old high-level interface, and add a new, better designed high-level interface". --Kazu From ben.franksen at online.de Sun Oct 15 19:10:20 2017 From: ben.franksen at online.de (Ben Franksen) Date: Sun, 15 Oct 2017 21:10:20 +0200 Subject: documentation bug in base Message-ID: Data.List claims: unlines is an inverse operation to lines. which I understand to mean prop> unlines (lines s) = s which is false in general. It should say prop> unlines (lines s) = if last s == '\n' then s else s ++ "\n" Cheers Ben From gershomb at gmail.com Mon Oct 16 22:17:19 2017 From: gershomb at gmail.com (Gershom B) Date: Mon, 16 Oct 2017 18:17:19 -0400 Subject: Proposal: add ordNub somewhere in containers Message-ID: There have been many discussions over the years about adding an efficient order preserving nub somewhere to our core libraries. It always comes down to the same issue: an efficient nub wants to be backed by an efficient `Set`, but the API of the `nub` itself doesn't make reference to any other data structures besides lists. So it feels a bit conceptually strange to put an efficient nub anywhere besides `Data.List` even though it can't go there without inverting our dependency tree in a weird way or inlining an efficient set implementation into the middle of it. Nonetheless, the convenience of having a good `nub` lying around in a core library is undeniable, and after writing the "usual" one in my code for the zillionth time, I decided to raise an issue about it: https://github.com/haskell/containers/issues/439 I was promptly directed here to make a proper proposal. So, here: 1) I propose two new functions, `ordNub` and `intNub` with the standard implementation (from https://github.com/nh2/haskell-ordnub): import qualified Data.Set as Set ordNub :: (Ord a) => [a] -> [a] ordNub l = go Set.empty l where go _ [] = [] go s (x:xs) = if x `Set.member` s then go s xs else x : go (Set.insert x s) xs and the same implementation, but specialized to `Int` and using `IntSet`s. The rationale for the names is that the former has a long history of use in folklore, and the latter is the obvious specialization of it. 2) I propose these functions be added to a new module in the `containers` library: `Data.Containers.ListUtils`. This can also potentially in the future add efficient list intersection, etc. as documented on the above reference link. The rationale for the new module is that it can provide a meaningful home for such functions which operate on lists, but require other data structures to be implemented efficiently... Discussion period: 2 weeks. --Gershom From david.feuer at gmail.com Mon Oct 16 22:44:41 2017 From: david.feuer at gmail.com (David Feuer) Date: Mon, 16 Oct 2017 18:44:41 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: I would imagine ordNub :: (Foldable t, Ord a) => t a -> [a] ordNub xs = foldr go (const []) xs Set.empty where go x r s | x `Set.member` s = r s | otherwise = x : r (Set.insert x s) which would suggest also ordNubR :: (Foldable t, Ord a) => t a -> [a] ordNubR xs = foldl go (const []) xs Set.empty where go r x s | x `Set.member` s = r s | otherwise = x : r (Set.insert x s) For containers biased the other way. Another question: do you have anything else you think should be stuck in the new module? On Oct 16, 2017 6:18 PM, "Gershom B" wrote: There have been many discussions over the years about adding an efficient order preserving nub somewhere to our core libraries. It always comes down to the same issue: an efficient nub wants to be backed by an efficient `Set`, but the API of the `nub` itself doesn't make reference to any other data structures besides lists. So it feels a bit conceptually strange to put an efficient nub anywhere besides `Data.List` even though it can't go there without inverting our dependency tree in a weird way or inlining an efficient set implementation into the middle of it. Nonetheless, the convenience of having a good `nub` lying around in a core library is undeniable, and after writing the "usual" one in my code for the zillionth time, I decided to raise an issue about it: https://github.com/haskell/containers/issues/439 I was promptly directed here to make a proper proposal. So, here: 1) I propose two new functions, `ordNub` and `intNub` with the standard implementation (from https://github.com/nh2/haskell-ordnub ): import qualified Data.Set as Set ordNub :: (Ord a) => [a] -> [a] ordNub l = go Set.empty l where go _ [] = [] go s (x:xs) = if x `Set.member` s then go s xs else x : go (Set.insert x s) xs and the same implementation, but specialized to `Int` and using `IntSet`s. The rationale for the names is that the former has a long history of use in folklore, and the latter is the obvious specialization of it. 2) I propose these functions be added to a new module in the `containers` library: `Data.Containers.ListUtils`. This can also potentially in the future add efficient list intersection, etc. as documented on the above reference link. The rationale for the new module is that it can provide a meaningful home for such functions which operate on lists, but require other data structures to be implemented efficiently... Discussion period: 2 weeks. --Gershom _______________________________________________ Libraries mailing list Libraries at haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries -------------- next part -------------- An HTML attachment was scrubbed... URL: From rpglover64 at gmail.com Tue Oct 17 05:44:18 2017 From: rpglover64 at gmail.com (Alex Rozenshteyn) Date: Tue, 17 Oct 2017 05:44:18 +0000 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: (Forgive me if I shouldn't be posting on libraries at . I did a little searching and couldn't determine if this list is supposed to be a public forum or not) > [D]o you have anything else you think should be stuck in the new module? As a user, I would expect to find the `...By` variants in the same location, but that precludes reusing `Set` without relying on complicated machinery like `reflection`, doesn't it? On Mon, Oct 16, 2017 at 3:45 PM David Feuer wrote: > I would imagine > > ordNub :: (Foldable t, Ord a) > => t a -> [a] > ordNub xs = foldr go (const []) xs Set.empty where > go x r s > | x `Set.member` s = r s > | otherwise = x : r (Set.insert x s) > > which would suggest also > > ordNubR :: (Foldable t, Ord a) > => t a -> [a] > ordNubR xs = foldl go (const []) xs Set.empty where > go r x s > | x `Set.member` s = r s > | otherwise = x : r (Set.insert x s) > > For containers biased the other way. > > Another question: do you have anything else you think should be stuck in > the new module? > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: > > There have been many discussions over the years about adding an > efficient order preserving nub somewhere to our core libraries. It > always comes down to the same issue: an efficient nub wants to be > backed by an efficient `Set`, but the API of the `nub` itself doesn't > make reference to any other data structures besides lists. So it feels > a bit conceptually strange to put an efficient nub anywhere besides > `Data.List` even though it can't go there without inverting our > dependency tree in a weird way or inlining an efficient set > implementation into the middle of it. > > Nonetheless, the convenience of having a good `nub` lying around in a > core library is undeniable, and after writing the "usual" one in my > code for the zillionth time, I decided to raise an issue about it: > > https://github.com/haskell/containers/issues/439 > > I was promptly directed here to make a proper proposal. > > So, here: > > 1) I propose two new functions, > > `ordNub` and `intNub` > > with the standard implementation (from > https://github.com/nh2/haskell-ordnub): > > import qualified Data.Set as Set > > ordNub :: (Ord a) => [a] -> [a] > ordNub l = go Set.empty l > where > go _ [] = [] > go s (x:xs) = if x `Set.member` s then go s xs > else x : go (Set.insert x s) xs > > and the same implementation, but specialized to `Int` and using `IntSet`s. > > The rationale for the names is that the former has a long history of > use in folklore, and the latter is the obvious specialization of it. > > 2) I propose these functions be added to a new module in the > `containers` library: `Data.Containers.ListUtils`. This can also > potentially in the future add efficient list intersection, etc. as > documented on the above reference link. > > The rationale for the new module is that it can provide a meaningful > home for such functions which operate on lists, but require other data > structures to be implemented efficiently... > > Discussion period: 2 weeks. > > --Gershom > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Tue Oct 17 05:54:24 2017 From: david.feuer at gmail.com (David Feuer) Date: Tue, 17 Oct 2017 01:54:24 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: Not really. We have access to the internals, so we *can* do that sort of thing. Should we? On Oct 17, 2017 1:44 AM, "Alex Rozenshteyn" wrote: > (Forgive me if I shouldn't be posting on libraries at . I did a little > searching and couldn't determine if this list is supposed to be a public > forum or not) > > > [D]o you have anything else you think should be stuck in the new module? > > As a user, I would expect to find the `...By` variants in the same > location, but that precludes reusing `Set` without relying on complicated > machinery like `reflection`, doesn't it? > > On Mon, Oct 16, 2017 at 3:45 PM David Feuer wrote: > >> I would imagine >> >> ordNub :: (Foldable t, Ord a) >> => t a -> [a] >> ordNub xs = foldr go (const []) xs Set.empty where >> go x r s >> | x `Set.member` s = r s >> | otherwise = x : r (Set.insert x s) >> >> which would suggest also >> >> ordNubR :: (Foldable t, Ord a) >> => t a -> [a] >> ordNubR xs = foldl go (const []) xs Set.empty where >> go r x s >> | x `Set.member` s = r s >> | otherwise = x : r (Set.insert x s) >> >> For containers biased the other way. >> >> Another question: do you have anything else you think should be stuck in >> the new module? >> >> On Oct 16, 2017 6:18 PM, "Gershom B" wrote: >> >> There have been many discussions over the years about adding an >> efficient order preserving nub somewhere to our core libraries. It >> always comes down to the same issue: an efficient nub wants to be >> backed by an efficient `Set`, but the API of the `nub` itself doesn't >> make reference to any other data structures besides lists. So it feels >> a bit conceptually strange to put an efficient nub anywhere besides >> `Data.List` even though it can't go there without inverting our >> dependency tree in a weird way or inlining an efficient set >> implementation into the middle of it. >> >> Nonetheless, the convenience of having a good `nub` lying around in a >> core library is undeniable, and after writing the "usual" one in my >> code for the zillionth time, I decided to raise an issue about it: >> >> https://github.com/haskell/containers/issues/439 >> >> I was promptly directed here to make a proper proposal. >> >> So, here: >> >> 1) I propose two new functions, >> >> `ordNub` and `intNub` >> >> with the standard implementation (from https://github.com/nh2/ >> haskell-ordnub): >> >> import qualified Data.Set as Set >> >> ordNub :: (Ord a) => [a] -> [a] >> ordNub l = go Set.empty l >> where >> go _ [] = [] >> go s (x:xs) = if x `Set.member` s then go s xs >> else x : go (Set.insert x s) xs >> >> and the same implementation, but specialized to `Int` and using `IntSet`s. >> >> The rationale for the names is that the former has a long history of >> use in folklore, and the latter is the obvious specialization of it. >> >> 2) I propose these functions be added to a new module in the >> `containers` library: `Data.Containers.ListUtils`. This can also >> potentially in the future add efficient list intersection, etc. as >> documented on the above reference link. >> >> The rationale for the new module is that it can provide a meaningful >> home for such functions which operate on lists, but require other data >> structures to be implemented efficiently... >> >> Discussion period: 2 weeks. >> >> --Gershom >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gershomb at gmail.com Tue Oct 17 06:09:48 2017 From: gershomb at gmail.com (Gershom B) Date: Tue, 17 Oct 2017 02:09:48 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: Good point on the by variants. (And indeed this is a public forum). Those can be written without any fancy machinery, just keeping the `by` data in the set, in the straightforward way. I agree it makes sense to add them. -g On October 17, 2017 at 1:44:30 AM, Alex Rozenshteyn (rpglover64 at gmail.com) wrote: > (Forgive me if I shouldn't be posting on libraries at . I did a little > searching and couldn't determine if this list is supposed to be a public > forum or not) > > > [D]o you have anything else you think should be stuck in the new module? > > As a user, I would expect to find the `...By` variants in the same > location, but that precludes reusing `Set` without relying on complicated > machinery like `reflection`, doesn't it? > > On Mon, Oct 16, 2017 at 3:45 PM David Feuer wrote: > > > I would imagine > > > > ordNub :: (Foldable t, Ord a) > > => t a -> [a] > > ordNub xs = foldr go (const []) xs Set.empty where > > go x r s > > | x `Set.member` s = r s > > | otherwise = x : r (Set.insert x s) > > > > which would suggest also > > > > ordNubR :: (Foldable t, Ord a) > > => t a -> [a] > > ordNubR xs = foldl go (const []) xs Set.empty where > > go r x s > > | x `Set.member` s = r s > > | otherwise = x : r (Set.insert x s) > > > > For containers biased the other way. > > > > Another question: do you have anything else you think should be stuck in > > the new module? > > > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: > > > > There have been many discussions over the years about adding an > > efficient order preserving nub somewhere to our core libraries. It > > always comes down to the same issue: an efficient nub wants to be > > backed by an efficient `Set`, but the API of the `nub` itself doesn't > > make reference to any other data structures besides lists. So it feels > > a bit conceptually strange to put an efficient nub anywhere besides > > `Data.List` even though it can't go there without inverting our > > dependency tree in a weird way or inlining an efficient set > > implementation into the middle of it. > > > > Nonetheless, the convenience of having a good `nub` lying around in a > > core library is undeniable, and after writing the "usual" one in my > > code for the zillionth time, I decided to raise an issue about it: > > > > https://github.com/haskell/containers/issues/439 > > > > I was promptly directed here to make a proper proposal. > > > > So, here: > > > > 1) I propose two new functions, > > > > `ordNub` and `intNub` > > > > with the standard implementation (from > > https://github.com/nh2/haskell-ordnub): > > > > import qualified Data.Set as Set > > > > ordNub :: (Ord a) => [a] -> [a] > > ordNub l = go Set.empty l > > where > > go _ [] = [] > > go s (x:xs) = if x `Set.member` s then go s xs > > else x : go (Set.insert x s) xs > > > > and the same implementation, but specialized to `Int` and using `IntSet`s. > > > > The rationale for the names is that the former has a long history of > > use in folklore, and the latter is the obvious specialization of it. > > > > 2) I propose these functions be added to a new module in the > > `containers` library: `Data.Containers.ListUtils`. This can also > > potentially in the future add efficient list intersection, etc. as > > documented on the above reference link. > > > > The rationale for the new module is that it can provide a meaningful > > home for such functions which operate on lists, but require other data > > structures to be implemented efficiently... > > > > Discussion period: 2 weeks. > > > > --Gershom > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > _______________________________________________ > > Libraries mailing list > > Libraries at haskell.org > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > From david.feuer at gmail.com Tue Oct 17 06:20:11 2017 From: david.feuer at gmail.com (David Feuer) Date: Tue, 17 Oct 2017 02:20:11 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: nubOn :: Ord b => (a -> b) -> [a] -> [a], or the Foldable version, seem just a bit safer, but less convenient. On Oct 17, 2017 2:09 AM, "Gershom B" wrote: > Good point on the by variants. (And indeed this is a public forum). > > Those can be written without any fancy machinery, just keeping the > `by` data in the set, in the straightforward way. I agree it makes > sense to add them. > > -g > > > On October 17, 2017 at 1:44:30 AM, Alex Rozenshteyn > (rpglover64 at gmail.com) wrote: > > (Forgive me if I shouldn't be posting on libraries at . I did a little > > searching and couldn't determine if this list is supposed to be a public > > forum or not) > > > > > [D]o you have anything else you think should be stuck in the new > module? > > > > As a user, I would expect to find the `...By` variants in the same > > location, but that precludes reusing `Set` without relying on complicated > > machinery like `reflection`, doesn't it? > > > > On Mon, Oct 16, 2017 at 3:45 PM David Feuer wrote: > > > > > I would imagine > > > > > > ordNub :: (Foldable t, Ord a) > > > => t a -> [a] > > > ordNub xs = foldr go (const []) xs Set.empty where > > > go x r s > > > | x `Set.member` s = r s > > > | otherwise = x : r (Set.insert x s) > > > > > > which would suggest also > > > > > > ordNubR :: (Foldable t, Ord a) > > > => t a -> [a] > > > ordNubR xs = foldl go (const []) xs Set.empty where > > > go r x s > > > | x `Set.member` s = r s > > > | otherwise = x : r (Set.insert x s) > > > > > > For containers biased the other way. > > > > > > Another question: do you have anything else you think should be stuck > in > > > the new module? > > > > > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: > > > > > > There have been many discussions over the years about adding an > > > efficient order preserving nub somewhere to our core libraries. It > > > always comes down to the same issue: an efficient nub wants to be > > > backed by an efficient `Set`, but the API of the `nub` itself doesn't > > > make reference to any other data structures besides lists. So it feels > > > a bit conceptually strange to put an efficient nub anywhere besides > > > `Data.List` even though it can't go there without inverting our > > > dependency tree in a weird way or inlining an efficient set > > > implementation into the middle of it. > > > > > > Nonetheless, the convenience of having a good `nub` lying around in a > > > core library is undeniable, and after writing the "usual" one in my > > > code for the zillionth time, I decided to raise an issue about it: > > > > > > https://github.com/haskell/containers/issues/439 > > > > > > I was promptly directed here to make a proper proposal. > > > > > > So, here: > > > > > > 1) I propose two new functions, > > > > > > `ordNub` and `intNub` > > > > > > with the standard implementation (from > > > https://github.com/nh2/haskell-ordnub): > > > > > > import qualified Data.Set as Set > > > > > > ordNub :: (Ord a) => [a] -> [a] > > > ordNub l = go Set.empty l > > > where > > > go _ [] = [] > > > go s (x:xs) = if x `Set.member` s then go s xs > > > else x : go (Set.insert x s) xs > > > > > > and the same implementation, but specialized to `Int` and using > `IntSet`s. > > > > > > The rationale for the names is that the former has a long history of > > > use in folklore, and the latter is the obvious specialization of it. > > > > > > 2) I propose these functions be added to a new module in the > > > `containers` library: `Data.Containers.ListUtils`. This can also > > > potentially in the future add efficient list intersection, etc. as > > > documented on the above reference link. > > > > > > The rationale for the new module is that it can provide a meaningful > > > home for such functions which operate on lists, but require other data > > > structures to be implemented efficiently... > > > > > > Discussion period: 2 weeks. > > > > > > --Gershom > > > _______________________________________________ > > > Libraries mailing list > > > Libraries at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > > > > _______________________________________________ > > > Libraries mailing list > > > Libraries at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Tue Oct 17 09:04:56 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 17 Oct 2017 11:04:56 +0200 (CEST) Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: On Mon, 16 Oct 2017, David Feuer wrote: > I would imagine > > ordNub :: (Foldable t, Ord a) >        => t a -> [a] The kind of generalization where the input is Foldable but the output is just a list looks pretty unnatural to me. I think it means that we still do not have the proper generalization that allows us to define ordNub :: (??? f, Ord a) => f a -> f a I would just leave it as ordNub :: (Ord a) => [a] -> [a] From etorreborre at yahoo.com Tue Oct 17 09:18:49 2017 From: etorreborre at yahoo.com (Eric Torreborre) Date: Tue, 17 Oct 2017 09:18:49 +0000 (UTC) Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: <266081147.373759.1508231929738@mail.yahoo.com> As a tangent I am interested in knowing what would be the typeclass for this sort of operation:  - take all the elements out of `f a` - do something with them with a function a -> b - insert the results back to get the same "original shape" `f b` In this case "do something with them" is "order them" but it could also be "invoke a function with all the 'a's and dispatch back the results" to allow "batching" function calls. ------------------------------------------------ Eric TORREBORRE T +49 176 420 8383 4 E etorreborre at yahoo.com P http://specs2.org B http://etorreborre.blogspot.com ------------------------------------------------ Le mardi 17 octobre 2017 à 11:05:43 UTC+2, Henning Thielemann a écrit : On Mon, 16 Oct 2017, David Feuer wrote: > I would imagine > > ordNub :: (Foldable t, Ord a) >        => t a -> [a] The kind of generalization where the input is Foldable but the output is just a list looks pretty unnatural to me. I think it means that we still do not have the proper generalization that allows us to define   ordNub :: (??? f, Ord a) => f a -> f a I would just leave it as ordNub :: (Ord a) => [a] -> [a]_______________________________________________ Libraries mailing list Libraries at haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Tue Oct 17 09:32:27 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 17 Oct 2017 11:32:27 +0200 (CEST) Subject: Proposal: add ordNub somewhere in containers In-Reply-To: <266081147.373759.1508231929738@mail.yahoo.com> References: <266081147.373759.1508231929738@mail.yahoo.com> Message-ID: On Tue, 17 Oct 2017, Eric Torreborre via Libraries wrote: > As a tangent I am interested in knowing what would be the typeclass for this sort of operation: > >  - take all the elements out of `f a` >  - do something with them with a function a -> b >  - insert the results back to get the same "original shape" `f b` I guess, this one can only be Functor. > In this case "do something with them" is "order them" A function of type (a -> b) would not be able to order elements. ordNub could be implemented using Traversable: catMaybes (traverse ??? xs :: [Maybe a]) You would only need a generalization for catMaybes like mfilter. From mike at barrucadu.co.uk Tue Oct 17 09:41:47 2017 From: mike at barrucadu.co.uk (Michael Walker) Date: Tue, 17 Oct 2017 10:41:47 +0100 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: <266081147.373759.1508231929738@mail.yahoo.com> Message-ID: > ordNub could be implemented using Traversable: > > catMaybes (traverse ??? xs :: [Maybe a]) > > You would only need a generalization for catMaybes like mfilter. The witherable package (https://hackage.haskell.org/package/witherable) has a typeclass generalising Traversable to containers which can remove elements. So I suspect Witherable is exactly the abstraction needed to write a polymorphic function: ordNub :: (Witherable f, Ord a) => f a -> f a ordNub = catMaybes . ordNub' ordNub' :: (Traversable f, Ord a) => f a -> f (Maybe a) ordNub; = ... -- Michael Walker (http://www.barrucadu.co.uk) From lemming at henning-thielemann.de Tue Oct 17 09:54:53 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 17 Oct 2017 11:54:53 +0200 (CEST) Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: <266081147.373759.1508231929738@mail.yahoo.com> Message-ID: On Tue, 17 Oct 2017, Henning Thielemann wrote: > ordNub could be implemented using Traversable: > > catMaybes (traverse ??? xs :: [Maybe a]) > > You would only need a generalization for catMaybes like mfilter. ordNub :: (Traversable f, MonadPlus f, Ord a) => f a -> f a ordNub = join . snd . Trav.mapAccumL (\s x -> if Set.member x s then (s,mzero) else (Set.insert x s, return x)) Set.empty We don't need mplus, only Monad and mzero. From rpglover64 at gmail.com Tue Oct 17 15:21:45 2017 From: rpglover64 at gmail.com (Alex Rozenshteyn) Date: Tue, 17 Oct 2017 15:21:45 +0000 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: > > nubOn :: Ord b => (a -> b) -> [a] -> [a], > or the Foldable version, seem just a bit safer, but less convenient. > I actually find the `...On` variants more convenient. I will often want to `nubBy ((==) `on` fst` (or `groupBy`), but rarely `nubBy (<=)`. > On Oct 17, 2017 2:09 AM, "Gershom B" wrote: > >> Good point on the by variants. (And indeed this is a public forum). >> >> Those can be written without any fancy machinery, just keeping the >> `by` data in the set, in the straightforward way. I agree it makes >> sense to add them. >> >> -g >> >> >> On October 17, 2017 at 1:44:30 AM, Alex Rozenshteyn >> (rpglover64 at gmail.com) wrote: >> > (Forgive me if I shouldn't be posting on libraries at . I did a little >> > searching and couldn't determine if this list is supposed to be a public >> > forum or not) >> > >> > > [D]o you have anything else you think should be stuck in the new >> module? >> > >> > As a user, I would expect to find the `...By` variants in the same >> > location, but that precludes reusing `Set` without relying on >> complicated >> > machinery like `reflection`, doesn't it? >> > >> > On Mon, Oct 16, 2017 at 3:45 PM David Feuer wrote: >> > >> > > I would imagine >> > > >> > > ordNub :: (Foldable t, Ord a) >> > > => t a -> [a] >> > > ordNub xs = foldr go (const []) xs Set.empty where >> > > go x r s >> > > | x `Set.member` s = r s >> > > | otherwise = x : r (Set.insert x s) >> > > >> > > which would suggest also >> > > >> > > ordNubR :: (Foldable t, Ord a) >> > > => t a -> [a] >> > > ordNubR xs = foldl go (const []) xs Set.empty where >> > > go r x s >> > > | x `Set.member` s = r s >> > > | otherwise = x : r (Set.insert x s) >> > > >> > > For containers biased the other way. >> > > >> > > Another question: do you have anything else you think should be stuck >> in >> > > the new module? >> > > >> > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: >> > > >> > > There have been many discussions over the years about adding an >> > > efficient order preserving nub somewhere to our core libraries. It >> > > always comes down to the same issue: an efficient nub wants to be >> > > backed by an efficient `Set`, but the API of the `nub` itself doesn't >> > > make reference to any other data structures besides lists. So it feels >> > > a bit conceptually strange to put an efficient nub anywhere besides >> > > `Data.List` even though it can't go there without inverting our >> > > dependency tree in a weird way or inlining an efficient set >> > > implementation into the middle of it. >> > > >> > > Nonetheless, the convenience of having a good `nub` lying around in a >> > > core library is undeniable, and after writing the "usual" one in my >> > > code for the zillionth time, I decided to raise an issue about it: >> > > >> > > https://github.com/haskell/containers/issues/439 >> > > >> > > I was promptly directed here to make a proper proposal. >> > > >> > > So, here: >> > > >> > > 1) I propose two new functions, >> > > >> > > `ordNub` and `intNub` >> > > >> > > with the standard implementation (from >> > > https://github.com/nh2/haskell-ordnub): >> > > >> > > import qualified Data.Set as Set >> > > >> > > ordNub :: (Ord a) => [a] -> [a] >> > > ordNub l = go Set.empty l >> > > where >> > > go _ [] = [] >> > > go s (x:xs) = if x `Set.member` s then go s xs >> > > else x : go (Set.insert x s) xs >> > > >> > > and the same implementation, but specialized to `Int` and using >> `IntSet`s. >> > > >> > > The rationale for the names is that the former has a long history of >> > > use in folklore, and the latter is the obvious specialization of it. >> > > >> > > 2) I propose these functions be added to a new module in the >> > > `containers` library: `Data.Containers.ListUtils`. This can also >> > > potentially in the future add efficient list intersection, etc. as >> > > documented on the above reference link. >> > > >> > > The rationale for the new module is that it can provide a meaningful >> > > home for such functions which operate on lists, but require other data >> > > structures to be implemented efficiently... >> > > >> > > Discussion period: 2 weeks. >> > > >> > > --Gershom >> > > _______________________________________________ >> > > Libraries mailing list >> > > Libraries at haskell.org >> > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > > >> > > >> > > _______________________________________________ >> > > Libraries mailing list >> > > Libraries at haskell.org >> > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > > >> > >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From andreas.abel at ifi.lmu.de Tue Oct 17 15:44:01 2017 From: andreas.abel at ifi.lmu.de (Andreas Abel) Date: Tue, 17 Oct 2017 17:44:01 +0200 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: <495b5aff-6e8c-d525-b79e-6d52b7518bf2@ifi.lmu.de> +1 for nubOn. This is a very useful generalization and no more work than implementing just nub. On 17.10.2017 17:21, Alex Rozenshteyn wrote: > nubOn :: Ord b => (a -> b) -> [a] -> [a], > or the Foldable version, seem just a bit safer, but less convenient. > > > I actually find the `...On` variants more convenient. I will often want > to `nubBy ((==) `on` fst` (or `groupBy`), but rarely `nubBy (<=)`. > > On Oct 17, 2017 2:09 AM, "Gershom B" > wrote: > > Good point on the by variants. (And indeed this is a public forum). > > Those can be written without any fancy machinery, just keeping the > `by` data in the set, in the straightforward way. I agree it makes > sense to add them. > > -g > > > On October 17, 2017 at 1:44:30 AM, Alex Rozenshteyn > (rpglover64 at gmail.com ) wrote: > > (Forgive me if I shouldn't be posting on libraries at . I did a > little > > searching and couldn't determine if this list is supposed to > be a public > > forum or not) > > > > > [D]o you have anything else you think should be stuck in > the new module? > > > > As a user, I would expect to find the `...By` variants in the > same > > location, but that precludes reusing `Set` without relying on > complicated > > machinery like `reflection`, doesn't it? > > > > On Mon, Oct 16, 2017 at 3:45 PM David Feuer wrote: > > > > > I would imagine > > > > > > ordNub :: (Foldable t, Ord a) > > > => t a -> [a] > > > ordNub xs = foldr go (const []) xs Set.empty where > > > go x r s > > > | x `Set.member` s = r s > > > | otherwise = x : r (Set.insert x s) > > > > > > which would suggest also > > > > > > ordNubR :: (Foldable t, Ord a) > > > => t a -> [a] > > > ordNubR xs = foldl go (const []) xs Set.empty where > > > go r x s > > > | x `Set.member` s = r s > > > | otherwise = x : r (Set.insert x s) > > > > > > For containers biased the other way. > > > > > > Another question: do you have anything else you think > should be stuck in > > > the new module? > > > > > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: > > > > > > There have been many discussions over the years about adding an > > > efficient order preserving nub somewhere to our core > libraries. It > > > always comes down to the same issue: an efficient nub wants > to be > > > backed by an efficient `Set`, but the API of the `nub` > itself doesn't > > > make reference to any other data structures besides lists. > So it feels > > > a bit conceptually strange to put an efficient nub anywhere > besides > > > `Data.List` even though it can't go there without inverting our > > > dependency tree in a weird way or inlining an efficient set > > > implementation into the middle of it. > > > > > > Nonetheless, the convenience of having a good `nub` lying > around in a > > > core library is undeniable, and after writing the "usual" > one in my > > > code for the zillionth time, I decided to raise an issue > about it: > > > > > > https://github.com/haskell/containers/issues/439 > > > > > > I was promptly directed here to make a proper proposal. > > > > > > So, here: > > > > > > 1) I propose two new functions, > > > > > > `ordNub` and `intNub` > > > > > > with the standard implementation (from > > > https://github.com/nh2/haskell-ordnub): > > > > > > import qualified Data.Set as Set > > > > > > ordNub :: (Ord a) => [a] -> [a] > > > ordNub l = go Set.empty l > > > where > > > go _ [] = [] > > > go s (x:xs) = if x `Set.member` s then go s xs > > > else x : go (Set.insert x s) xs > > > > > > and the same implementation, but specialized to `Int` and > using `IntSet`s. > > > > > > The rationale for the names is that the former has a long > history of > > > use in folklore, and the latter is the obvious > specialization of it. > > > > > > 2) I propose these functions be added to a new module in the > > > `containers` library: `Data.Containers.ListUtils`. This can > also > > > potentially in the future add efficient list intersection, > etc. as > > > documented on the above reference link. > > > > > > The rationale for the new module is that it can provide a > meaningful > > > home for such functions which operate on lists, but require > other data > > > structures to be implemented efficiently... > > > > > > Discussion period: 2 weeks. > > > > > > --Gershom > > > _______________________________________________ > > > Libraries mailing list > > > Libraries at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > > > > _______________________________________________ > > > Libraries mailing list > > > Libraries at haskell.org > > > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www.cse.chalmers.se/~abela/ From hvriedel at gmail.com Wed Oct 18 12:35:26 2017 From: hvriedel at gmail.com (Herbert Valerio Riedel) Date: Wed, 18 Oct 2017 14:35:26 +0200 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: (Gershom B.'s message of "Mon, 16 Oct 2017 18:17:19 -0400") References: Message-ID: <87mv4oprap.fsf@gmail.com> On 2017-10-16 at 18:17:19 -0400, Gershom B wrote: [...] > 1) I propose two new functions, > > `ordNub` and `intNub` > > with the standard implementation (from https://github.com/nh2/haskell-ordnub): > > import qualified Data.Set as Set > > ordNub :: (Ord a) => [a] -> [a] > ordNub l = go Set.empty l > where > go _ [] = [] > go s (x:xs) = if x `Set.member` s then go s xs > else x : go (Set.insert x s) xs > > and the same implementation, but specialized to `Int` and using `IntSet`s. I'm generally +1 for an 'ordNub'; I don't mind the particular color of the shed. While at it, I'd like to use the occasion to point out two minor things with that specific implementation: a) One thing I've been missing from `container's API are "UPSERT"-ish operations; In the case of `Set`, the implementation above performs a lookup, and then has to start the insertion from scratch. If we had something like, Set.tryInsert :: Ord a => a -> Set a -> (Set a, Bool) or Set.tryInsert :: Ord a => a -> Set a -> Maybe (Set a) `ordNub` would benefit. b) This is more of an observation, as there's not much we can do here with little effort: iirc, `nub` has a worst-case space complexity (if the input list is made up of N distinct values, e.g. (`nub [1..n] :: [Int])) of 3N words for the [a]-spine to keep track of the already seen values. Using `Set` however trades time-complexity for memory-complexity, and needs 5N words for the 'Set a'-spine. c.f. http://blog.johantibell.com/2011/06/memory-footprints-of-some-common-data.html -- hvr -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 818 bytes Desc: not available URL: From mail at nh2.me Wed Oct 18 17:25:42 2017 From: mail at nh2.me (=?UTF-8?Q?Niklas_Hamb=c3=bcchen?=) Date: Wed, 18 Oct 2017 19:25:42 +0200 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: <0d1f0343-5e6d-e3e1-5abb-9fbaa3448d62@nh2.me> I guess it goes without saying that I'm +1 on this issue. Like you have I copied ordNub hundreds of times, and debugged clients' code slow performance for hours and hours, as due to lack of an easily available nub alternative they longed for nub. It would be great if this could finally come to an end. From david.feuer at gmail.com Wed Oct 18 17:49:22 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 18 Oct 2017 13:49:22 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: I am convinced that we should add ordNub :: Ord a => [a] -> [a] ordNubOn :: Ord b => (a -> b) -> [a] -> [b] intNub :: [Int] -> [Int] intNubOn :: (a -> Int) -> [a] -> [a] And because nub preserves non-emptiness, I believe we should also offer ordNub1 :: Ord a => NonEmpty a -> NonEmpty a ordNubOn1 :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a intNub1 :: NonEmpty Int -> NonEmpty Int intNubOn1 :: (a -> Int) -> NonEmpty a -> NonEmpty a I imagine we should also add these operations for Data.Sequence.Seq. I'm not yet convinced that we should add ordNubBy :: (a -> a -> Ordering) -> [a] -> [a] but I'm open to further discussion of that question. My main concern is that the properties of the comparison argument require careful documentation. In its favor, using it improperly cannot *expose* a broken Set to later operations. I would very much like to hear further bikeshedding around names and namespaces. On Oct 16, 2017 6:18 PM, "Gershom B" wrote: > There have been many discussions over the years about adding an > efficient order preserving nub somewhere to our core libraries. It > always comes down to the same issue: an efficient nub wants to be > backed by an efficient `Set`, but the API of the `nub` itself doesn't > make reference to any other data structures besides lists. So it feels > a bit conceptually strange to put an efficient nub anywhere besides > `Data.List` even though it can't go there without inverting our > dependency tree in a weird way or inlining an efficient set > implementation into the middle of it. > > Nonetheless, the convenience of having a good `nub` lying around in a > core library is undeniable, and after writing the "usual" one in my > code for the zillionth time, I decided to raise an issue about it: > > https://github.com/haskell/containers/issues/439 > > I was promptly directed here to make a proper proposal. > > So, here: > > 1) I propose two new functions, > > `ordNub` and `intNub` > > with the standard implementation (from https://github.com/nh2/ > haskell-ordnub): > > import qualified Data.Set as Set > > ordNub :: (Ord a) => [a] -> [a] > ordNub l = go Set.empty l > where > go _ [] = [] > go s (x:xs) = if x `Set.member` s then go s xs > else x : go (Set.insert x s) xs > > and the same implementation, but specialized to `Int` and using `IntSet`s. > > The rationale for the names is that the former has a long history of > use in folklore, and the latter is the obvious specialization of it. > > 2) I propose these functions be added to a new module in the > `containers` library: `Data.Containers.ListUtils`. This can also > potentially in the future add efficient list intersection, etc. as > documented on the above reference link. > > The rationale for the new module is that it can provide a meaningful > home for such functions which operate on lists, but require other data > structures to be implemented efficiently... > > Discussion period: 2 weeks. > > --Gershom > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gershomb at gmail.com Wed Oct 18 21:28:37 2017 From: gershomb at gmail.com (Gershom B) Date: Wed, 18 Oct 2017 17:28:37 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: I agree that `ordNubOn` suffices and we don't need `ordNubBy` since there's nothing lawful you can do with the latter that you can't do with the former. I'm indifferent on the NonEmpty and Seq case as I don't suspect that they will yield much more efficient implementations than going via lists, especially if we setup (and we should!) the fusion rules correctly. I have no objection to adding them for completeness however. If we do add them, then the proposed module name `Data.Containers.ListUtils` becomes slightly less appropriate, but I think still fine, since these are "morally" all lists of various sorts. -g On Wed, Oct 18, 2017 at 1:49 PM, David Feuer wrote: > I am convinced that we should add > > ordNub :: Ord a => [a] -> [a] > ordNubOn :: Ord b => (a -> b) -> [a] -> [b] > intNub :: [Int] -> [Int] > intNubOn :: (a -> Int) -> [a] -> [a] > > And because nub preserves non-emptiness, I believe we should also offer > > ordNub1 :: Ord a => NonEmpty a -> NonEmpty a > ordNubOn1 :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a > intNub1 :: NonEmpty Int -> NonEmpty Int > intNubOn1 :: (a -> Int) -> NonEmpty a -> NonEmpty a > > I imagine we should also add these operations for Data.Sequence.Seq. > > I'm not yet convinced that we should add > > ordNubBy :: (a -> a -> Ordering) -> [a] -> [a] > > but I'm open to further discussion of that question. My main concern is that > the properties of the comparison argument require careful documentation. In > its favor, using it improperly cannot *expose* a broken Set to later > operations. > > I would very much like to hear further bikeshedding around names and > namespaces. > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: >> >> There have been many discussions over the years about adding an >> efficient order preserving nub somewhere to our core libraries. It >> always comes down to the same issue: an efficient nub wants to be >> backed by an efficient `Set`, but the API of the `nub` itself doesn't >> make reference to any other data structures besides lists. So it feels >> a bit conceptually strange to put an efficient nub anywhere besides >> `Data.List` even though it can't go there without inverting our >> dependency tree in a weird way or inlining an efficient set >> implementation into the middle of it. >> >> Nonetheless, the convenience of having a good `nub` lying around in a >> core library is undeniable, and after writing the "usual" one in my >> code for the zillionth time, I decided to raise an issue about it: >> >> https://github.com/haskell/containers/issues/439 >> >> I was promptly directed here to make a proper proposal. >> >> So, here: >> >> 1) I propose two new functions, >> >> `ordNub` and `intNub` >> >> with the standard implementation (from >> https://github.com/nh2/haskell-ordnub): >> >> import qualified Data.Set as Set >> >> ordNub :: (Ord a) => [a] -> [a] >> ordNub l = go Set.empty l >> where >> go _ [] = [] >> go s (x:xs) = if x `Set.member` s then go s xs >> else x : go (Set.insert x s) xs >> >> and the same implementation, but specialized to `Int` and using `IntSet`s. >> >> The rationale for the names is that the former has a long history of >> use in folklore, and the latter is the obvious specialization of it. >> >> 2) I propose these functions be added to a new module in the >> `containers` library: `Data.Containers.ListUtils`. This can also >> potentially in the future add efficient list intersection, etc. as >> documented on the above reference link. >> >> The rationale for the new module is that it can provide a meaningful >> home for such functions which operate on lists, but require other data >> structures to be implemented efficiently... >> >> Discussion period: 2 weeks. >> >> --Gershom >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From david.feuer at gmail.com Wed Oct 18 21:40:10 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 18 Oct 2017 17:40:10 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: The trouble with NonEmpty is that I don't like the idea of users having to roll their own. They'd end up looking like case ordNub (toList xs) of [] -> error "can't happen!" x : xs -> x :| xs I hate "can't happen" errors! The case for sequences is less compelling with fusion, for sure, but it seems a bit strange to leave them out. On Oct 18, 2017 5:28 PM, "Gershom B" wrote: > I agree that `ordNubOn` suffices and we don't need `ordNubBy` since > there's nothing lawful you can do with the latter that you can't do > with the former. I'm indifferent on the NonEmpty and Seq case as I > don't suspect that they will yield much more efficient implementations > than going via lists, especially if we setup (and we should!) the > fusion rules correctly. I have no objection to adding them for > completeness however. > > If we do add them, then the proposed module name > `Data.Containers.ListUtils` becomes slightly less appropriate, but I > think still fine, since these are "morally" all lists of various > sorts. > > -g > > > On Wed, Oct 18, 2017 at 1:49 PM, David Feuer > wrote: > > I am convinced that we should add > > > > ordNub :: Ord a => [a] -> [a] > > ordNubOn :: Ord b => (a -> b) -> [a] -> [b] > > intNub :: [Int] -> [Int] > > intNubOn :: (a -> Int) -> [a] -> [a] > > > > And because nub preserves non-emptiness, I believe we should also offer > > > > ordNub1 :: Ord a => NonEmpty a -> NonEmpty a > > ordNubOn1 :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a > > intNub1 :: NonEmpty Int -> NonEmpty Int > > intNubOn1 :: (a -> Int) -> NonEmpty a -> NonEmpty a > > > > I imagine we should also add these operations for Data.Sequence.Seq. > > > > I'm not yet convinced that we should add > > > > ordNubBy :: (a -> a -> Ordering) -> [a] -> [a] > > > > but I'm open to further discussion of that question. My main concern is > that > > the properties of the comparison argument require careful documentation. > In > > its favor, using it improperly cannot *expose* a broken Set to later > > operations. > > > > I would very much like to hear further bikeshedding around names and > > namespaces. > > > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: > >> > >> There have been many discussions over the years about adding an > >> efficient order preserving nub somewhere to our core libraries. It > >> always comes down to the same issue: an efficient nub wants to be > >> backed by an efficient `Set`, but the API of the `nub` itself doesn't > >> make reference to any other data structures besides lists. So it feels > >> a bit conceptually strange to put an efficient nub anywhere besides > >> `Data.List` even though it can't go there without inverting our > >> dependency tree in a weird way or inlining an efficient set > >> implementation into the middle of it. > >> > >> Nonetheless, the convenience of having a good `nub` lying around in a > >> core library is undeniable, and after writing the "usual" one in my > >> code for the zillionth time, I decided to raise an issue about it: > >> > >> https://github.com/haskell/containers/issues/439 > >> > >> I was promptly directed here to make a proper proposal. > >> > >> So, here: > >> > >> 1) I propose two new functions, > >> > >> `ordNub` and `intNub` > >> > >> with the standard implementation (from > >> https://github.com/nh2/haskell-ordnub): > >> > >> import qualified Data.Set as Set > >> > >> ordNub :: (Ord a) => [a] -> [a] > >> ordNub l = go Set.empty l > >> where > >> go _ [] = [] > >> go s (x:xs) = if x `Set.member` s then go s xs > >> else x : go (Set.insert x s) xs > >> > >> and the same implementation, but specialized to `Int` and using > `IntSet`s. > >> > >> The rationale for the names is that the former has a long history of > >> use in folklore, and the latter is the obvious specialization of it. > >> > >> 2) I propose these functions be added to a new module in the > >> `containers` library: `Data.Containers.ListUtils`. This can also > >> potentially in the future add efficient list intersection, etc. as > >> documented on the above reference link. > >> > >> The rationale for the new module is that it can provide a meaningful > >> home for such functions which operate on lists, but require other data > >> structures to be implemented efficiently... > >> > >> Discussion period: 2 weeks. > >> > >> --Gershom > >> _______________________________________________ > >> Libraries mailing list > >> Libraries at haskell.org > >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -------------- next part -------------- An HTML attachment was scrubbed... URL: From gershomb at gmail.com Wed Oct 18 21:45:14 2017 From: gershomb at gmail.com (Gershom B) Date: Wed, 18 Oct 2017 17:45:14 -0400 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: Vis a vis NonEmpty, base provides a partial `fromList`, much as I dislike it. Hence, the proper "roll your own" is `fromList . ordNub . toList`. --Gershom On Wed, Oct 18, 2017 at 5:40 PM, David Feuer wrote: > The trouble with NonEmpty is that I don't like the idea of users having to > roll their own. They'd end up looking like > > case ordNub (toList xs) of > [] -> error "can't happen!" > x : xs -> x :| xs > > I hate "can't happen" errors! > > The case for sequences is less compelling with fusion, for sure, but it > seems a bit strange to leave them out. > > On Oct 18, 2017 5:28 PM, "Gershom B" wrote: >> >> I agree that `ordNubOn` suffices and we don't need `ordNubBy` since >> there's nothing lawful you can do with the latter that you can't do >> with the former. I'm indifferent on the NonEmpty and Seq case as I >> don't suspect that they will yield much more efficient implementations >> than going via lists, especially if we setup (and we should!) the >> fusion rules correctly. I have no objection to adding them for >> completeness however. >> >> If we do add them, then the proposed module name >> `Data.Containers.ListUtils` becomes slightly less appropriate, but I >> think still fine, since these are "morally" all lists of various >> sorts. >> >> -g >> >> >> On Wed, Oct 18, 2017 at 1:49 PM, David Feuer >> wrote: >> > I am convinced that we should add >> > >> > ordNub :: Ord a => [a] -> [a] >> > ordNubOn :: Ord b => (a -> b) -> [a] -> [b] >> > intNub :: [Int] -> [Int] >> > intNubOn :: (a -> Int) -> [a] -> [a] >> > >> > And because nub preserves non-emptiness, I believe we should also offer >> > >> > ordNub1 :: Ord a => NonEmpty a -> NonEmpty a >> > ordNubOn1 :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a >> > intNub1 :: NonEmpty Int -> NonEmpty Int >> > intNubOn1 :: (a -> Int) -> NonEmpty a -> NonEmpty a >> > >> > I imagine we should also add these operations for Data.Sequence.Seq. >> > >> > I'm not yet convinced that we should add >> > >> > ordNubBy :: (a -> a -> Ordering) -> [a] -> [a] >> > >> > but I'm open to further discussion of that question. My main concern is >> > that >> > the properties of the comparison argument require careful documentation. >> > In >> > its favor, using it improperly cannot *expose* a broken Set to later >> > operations. >> > >> > I would very much like to hear further bikeshedding around names and >> > namespaces. >> > >> > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: >> >> >> >> There have been many discussions over the years about adding an >> >> efficient order preserving nub somewhere to our core libraries. It >> >> always comes down to the same issue: an efficient nub wants to be >> >> backed by an efficient `Set`, but the API of the `nub` itself doesn't >> >> make reference to any other data structures besides lists. So it feels >> >> a bit conceptually strange to put an efficient nub anywhere besides >> >> `Data.List` even though it can't go there without inverting our >> >> dependency tree in a weird way or inlining an efficient set >> >> implementation into the middle of it. >> >> >> >> Nonetheless, the convenience of having a good `nub` lying around in a >> >> core library is undeniable, and after writing the "usual" one in my >> >> code for the zillionth time, I decided to raise an issue about it: >> >> >> >> https://github.com/haskell/containers/issues/439 >> >> >> >> I was promptly directed here to make a proper proposal. >> >> >> >> So, here: >> >> >> >> 1) I propose two new functions, >> >> >> >> `ordNub` and `intNub` >> >> >> >> with the standard implementation (from >> >> https://github.com/nh2/haskell-ordnub): >> >> >> >> import qualified Data.Set as Set >> >> >> >> ordNub :: (Ord a) => [a] -> [a] >> >> ordNub l = go Set.empty l >> >> where >> >> go _ [] = [] >> >> go s (x:xs) = if x `Set.member` s then go s xs >> >> else x : go (Set.insert x s) xs >> >> >> >> and the same implementation, but specialized to `Int` and using >> >> `IntSet`s. >> >> >> >> The rationale for the names is that the former has a long history of >> >> use in folklore, and the latter is the obvious specialization of it. >> >> >> >> 2) I propose these functions be added to a new module in the >> >> `containers` library: `Data.Containers.ListUtils`. This can also >> >> potentially in the future add efficient list intersection, etc. as >> >> documented on the above reference link. >> >> >> >> The rationale for the new module is that it can provide a meaningful >> >> home for such functions which operate on lists, but require other data >> >> structures to be implemented efficiently... >> >> >> >> Discussion period: 2 weeks. >> >> >> >> --Gershom >> >> _______________________________________________ >> >> Libraries mailing list >> >> Libraries at haskell.org >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From mgsloan at gmail.com Wed Oct 18 22:22:17 2017 From: mgsloan at gmail.com (Michael Sloan) Date: Wed, 18 Oct 2017 15:22:17 -0700 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: On Wed, Oct 18, 2017 at 10:49 AM, David Feuer wrote: > I am convinced that we should add > > ordNub :: Ord a => [a] -> [a] > ordNubOn :: Ord b => (a -> b) -> [a] -> [b] > intNub :: [Int] -> [Int] > intNubOn :: (a -> Int) -> [a] -> [a] +1 to ordNub / ordNubOn, and having the documentation for nub mention that you probably want ordNub in nearly all cases. +1 to intNub / intNubOn, with RULES pragma to specialize ordNub / ordNubOn to it. > And because nub preserves non-emptiness, I believe we should also offer > > ordNub1 :: Ord a => NonEmpty a -> NonEmpty a > ordNubOn1 :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a > intNub1 :: NonEmpty Int -> NonEmpty Int > intNubOn1 :: (a -> Int) -> NonEmpty a -> NonEmpty a I wish these could go in base. It would be export these from Data.List.NonEmpty, using the same names as the list operations, but this is not possible due to the implementation in terms of Set. > I imagine we should also add these operations for Data.Sequence.Seq. +1 > I'm not yet convinced that we should add > > ordNubBy :: (a -> a -> Ordering) -> [a] -> [a] Such an operation is quite useful, though unfortunately it does not fit naturally into an implementation in terms of Set. There are quite reasonable use-cases here, where even a hack with a new datatype could be quite convoluted. I recently used a "sortNubBy" in a client project. Perhaps that should be another proposal - it is something that could be in base, though less efficient. In particular, this function is useful in cases where the ordering depends on some value other than the value of the element. Another, more common case, is ignoring some distinctions between values, such as ignoring a field. Sure, you can make a newtype and use "coerce" for this, but I don't like using "coerce" because in general it can break invariants. Much better than unsafeCoerce, of course, but still unsafe. I'd rather not create an Ord instance just to use it in one place, it seems like unnecessary plumbing. > but I'm open to further discussion of that question. My main concern is that > the properties of the comparison argument require careful documentation. In > its favor, using it improperly cannot *expose* a broken Set to later > operations. > > I would very much like to hear further bikeshedding around names and > namespaces. > > On Oct 16, 2017 6:18 PM, "Gershom B" wrote: >> >> There have been many discussions over the years about adding an >> efficient order preserving nub somewhere to our core libraries. It >> always comes down to the same issue: an efficient nub wants to be >> backed by an efficient `Set`, but the API of the `nub` itself doesn't >> make reference to any other data structures besides lists. So it feels >> a bit conceptually strange to put an efficient nub anywhere besides >> `Data.List` even though it can't go there without inverting our >> dependency tree in a weird way or inlining an efficient set >> implementation into the middle of it. >> >> Nonetheless, the convenience of having a good `nub` lying around in a >> core library is undeniable, and after writing the "usual" one in my >> code for the zillionth time, I decided to raise an issue about it: >> >> https://github.com/haskell/containers/issues/439 >> >> I was promptly directed here to make a proper proposal. >> >> So, here: >> >> 1) I propose two new functions, >> >> `ordNub` and `intNub` >> >> with the standard implementation (from >> https://github.com/nh2/haskell-ordnub): >> >> import qualified Data.Set as Set >> >> ordNub :: (Ord a) => [a] -> [a] >> ordNub l = go Set.empty l >> where >> go _ [] = [] >> go s (x:xs) = if x `Set.member` s then go s xs >> else x : go (Set.insert x s) xs >> >> and the same implementation, but specialized to `Int` and using `IntSet`s. >> >> The rationale for the names is that the former has a long history of >> use in folklore, and the latter is the obvious specialization of it. >> >> 2) I propose these functions be added to a new module in the >> `containers` library: `Data.Containers.ListUtils`. This can also >> potentially in the future add efficient list intersection, etc. as >> documented on the above reference link. >> >> The rationale for the new module is that it can provide a meaningful >> home for such functions which operate on lists, but require other data >> structures to be implemented efficiently... >> >> Discussion period: 2 weeks. >> >> --Gershom >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From lemming at henning-thielemann.de Thu Oct 19 07:50:47 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Thu, 19 Oct 2017 09:50:47 +0200 (CEST) Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: On Wed, 18 Oct 2017, Gershom B wrote: > Vis a vis NonEmpty, base provides a partial `fromList`, much as I > dislike it. Hence, the proper "roll your own" is `fromList . ordNub . > toList`. My idea of NonEmpty is to prove totality by implementation. I'd prefer a custom obviously total implementation of NonEmpty.ordNub. From abela at chalmers.se Thu Oct 19 08:00:11 2017 From: abela at chalmers.se (Andreas Abel) Date: Thu, 19 Oct 2017 10:00:11 +0200 Subject: Proposal: add ordNub somewhere in containers In-Reply-To: References: Message-ID: Your current proposal sounds fine, I think it is safe to go ahead. > ordNubBy :: (a -> a -> Ordering) -> [a] -> [a] can be taken at a second step, if there is no consensus now. Personally, I would include it. On 18.10.2017 19:49, David Feuer wrote: > I am convinced that we should add > > ordNub :: Ord a => [a] -> [a] > ordNubOn :: Ord b => (a -> b) -> [a] -> [b] > intNub :: [Int] -> [Int] > intNubOn :: (a -> Int) -> [a] -> [a] > > And because nub preserves non-emptiness, I believe we should also offer > > ordNub1 :: Ord a => NonEmpty a -> NonEmpty a > ordNubOn1 :: Ord b => (a -> b) -> NonEmpty a -> NonEmpty a > intNub1 :: NonEmpty Int -> NonEmpty Int > intNubOn1 :: (a -> Int) -> NonEmpty a -> NonEmpty a > > I imagine we should also add these operations for Data.Sequence.Seq. > > I'm not yet convinced that we should add > > ordNubBy :: (a -> a -> Ordering) -> [a] -> [a] > > but I'm open to further discussion of that question. My main concern is > that the properties of the comparison argument require careful > documentation. In its favor, using it improperly cannot *expose* a > broken Set to later operations. > > I would very much like to hear further bikeshedding around names and > namespaces. > > On Oct 16, 2017 6:18 PM, "Gershom B" > wrote: > > There have been many discussions over the years about adding an > efficient order preserving nub somewhere to our core libraries. It > always comes down to the same issue: an efficient nub wants to be > backed by an efficient `Set`, but the API of the `nub` itself doesn't > make reference to any other data structures besides lists. So it feels > a bit conceptually strange to put an efficient nub anywhere besides > `Data.List` even though it can't go there without inverting our > dependency tree in a weird way or inlining an efficient set > implementation into the middle of it. > > Nonetheless, the convenience of having a good `nub` lying around in a > core library is undeniable, and after writing the "usual" one in my > code for the zillionth time, I decided to raise an issue about it: > > https://github.com/haskell/containers/issues/439 > > > I was promptly directed here to make a proper proposal. > > So, here: > > 1) I propose two new functions, > > `ordNub` and `intNub` > > with the standard implementation (from > https://github.com/nh2/haskell-ordnub > ): > > import qualified Data.Set as Set > > ordNub :: (Ord a) => [a] -> [a] > ordNub l = go Set.empty l >   where >     go _ [] = [] >     go s (x:xs) = if x `Set.member` s then go s xs >                                       else x : go (Set.insert x s) xs > > and the same implementation, but specialized to `Int` and using > `IntSet`s. > > The rationale for the names is that the former has a long history of > use in folklore, and the latter is the obvious specialization of it. > > 2) I propose these functions be added to a new module in the > `containers` library: `Data.Containers.ListUtils`. This can also > potentially in the future add efficient list intersection, etc. as > documented on the above reference link. > > The rationale for the new module is that it can provide a meaningful > home for such functions which operate on lists, but require other data > structures to be implemented efficiently... > > Discussion period: 2 weeks. > > --Gershom > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www.cse.chalmers.se/~abela/ From mail at joachim-breitner.de Fri Oct 20 14:14:38 2017 From: mail at joachim-breitner.de (Joachim Breitner) Date: Fri, 20 Oct 2017 10:14:38 -0400 Subject: Proposal: add nubOrd somewhere in containers In-Reply-To: References: Message-ID: <1508508878.960.2.camel@joachim-breitner.de> Hi, Am Mittwoch, den 18.10.2017, 13:49 -0400 schrieb David Feuer: > I am convinced that we should add > > ordNub :: Ord a => [a] -> [a] > ordNubOn :: Ord b => (a -> b) -> [a] -> [b] > intNub :: [Int] -> [Int] > intNubOn :: (a -> Int) -> [a] -> [a] can we shed the names a bit? I think the operation “nubbing” should be first, and the details (”…On”, “…By”, “…OrdOn”, “Ord”, “Int”) should be the second component. This would also have the advantage of listing all ”nub” variants together in an index. So: nubOrd :: Ord a => [a] -> [a] nubOrdOn :: Ord b => (a -> b) -> [a] -> [b] nubInt :: [Int] -> [Int] nubIntOn :: (a -> Int) -> [a] -> [a] This is consistent with, say “map” vs. “mapM” and other suffix-based naming in the libraries. Greetings, Joachim -- Joachim Breitner mail at joachim-breitner.de http://www.joachim-breitner.de/ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part URL: From eacameron at gmail.com Fri Oct 20 14:20:19 2017 From: eacameron at gmail.com (Elliot Cameron) Date: Fri, 20 Oct 2017 10:20:19 -0400 Subject: Proposal: add nubOrd somewhere in containers In-Reply-To: <1508508878.960.2.camel@joachim-breitner.de> References: <1508508878.960.2.camel@joachim-breitner.de> Message-ID: That's also consistent with the commonly used "extra" package: https://hackage.haskell.org/package/extra-1.6/docs/Data-List-Extra.html#v:nubOrd On Fri, Oct 20, 2017 at 10:14 AM, Joachim Breitner wrote: > Hi, > > Am Mittwoch, den 18.10.2017, 13:49 -0400 schrieb David Feuer: > > I am convinced that we should add > > > > ordNub :: Ord a => [a] -> [a] > > ordNubOn :: Ord b => (a -> b) -> [a] -> [b] > > intNub :: [Int] -> [Int] > > intNubOn :: (a -> Int) -> [a] -> [a] > > can we shed the names a bit? I think the operation “nubbing” should be > first, and the details (”…On”, “…By”, “…OrdOn”, “Ord”, “Int”) should be > the second component. This would also have the advantage of listing all > ”nub” variants together in an index. > > So: > > nubOrd :: Ord a => [a] -> [a] > nubOrdOn :: Ord b => (a -> b) -> [a] -> [b] > nubInt :: [Int] -> [Int] > nubIntOn :: (a -> Int) -> [a] -> [a] > > This is consistent with, say “map” vs. “mapM” and other suffix-based > naming in the libraries. > > > Greetings, > Joachim > -- > Joachim Breitner > mail at joachim-breitner.de > http://www.joachim-breitner.de/ > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From zemyla at gmail.com Sat Oct 21 18:00:15 2017 From: zemyla at gmail.com (Zemyla) Date: Sat, 21 Oct 2017 13:00:15 -0500 Subject: Proposal: Add "Alternative" instance for ZipList, as well as Semigroup and Monoid Message-ID: This paper on monoids and near-semirings gives an Alternative instance for ZipList consistent with its Applicative instance: https://lirias.kuleuven.be/bitstream/123456789/499951/1/main.pdf The original definition of (<|>) leaves a lot to be desired, because it iterates through the first list twice, preventing inlining of xs: ZipList xs <|> ZipList ys = ZipList $ xs ++ drop (length xs) ys Edited for efficiency, it winds up being: instance Alternative ZipList where empty = ZipList [] ZipList xs <|> ZipList ys = ZipList $ go xs ys where go [] ys = ys go xs [] = xs go (x:xs) (_:ys) = x:go xs ys A different formulation, using foldr/build, goes like this: ZipList xs <|> ZipList ys = ZipList $ build $ \c z -> let goX x xr !n = c x $ xr $ n + 1 goY y yr n | n <= 0 = c y $ yr 0 | otherwise = yr $ n - 1 in foldr goX (foldr goY (const z) ys) ys (0 :: Int) It is an idempotent monoid, and sconcat/mconcat can be written as follows: zlconcat :: Foldable t => t (ZipList a) -> ZipList a zlconcat xss = ZipList $ build $ \c z -> let goO (ZipList xs) xr !n = foldr goI endI xs 0 where goI x xk i | i < n = xk $ i + 1 | otherwise = c x $ xk $ i + 1 endI i = if i < n then xr n else xr i in foldr goO (const z) xss (0 :: Int) So in the end, the Semigroup/Monoid instances look like: instance Semigroup (ZipList a) where (<>) = (<|>) sconcat = zlconcat stimes = stimesIdempotentMonoid instance Monoid (ZipList a) where mempty = empty mappend = (<|>) mconcat = zlconcat Sadly, the paper doesn't prove that it's a valid left catch Alternative, and sort of mentions it offhand, but tests suggest it is associative, [] is obviously the identity for <|> and the zero for <*>, and pure a <|> x = pure a. Any ideas on which implementation to prefer, or different ideas for implementing sconcat/mconcat?