From ben.franksen at online.de Tue Dec 1 09:16:43 2020 From: ben.franksen at online.de (Ben Franksen) Date: Tue, 1 Dec 2020 10:16:43 +0100 Subject: containers: symmetricDifference for Set and HashSet Message-ID: Would it make sense to add a function like the following to containers: symmetricDifference :: Set a -> Set a -> (Set a, Set a, Set a) symmetricDifference a b = (a \\ b, a `intersection` b, b \\ a) with the idea that this can be implemented more efficiently as a primitive than the above specification? (And similarly for HashSet.) If this is the case, then perhaps difference and intersection could be defined in terms of this new primitive: difference a b = let (r, _, _) = symmetricDifference in r intersection a b = let (_, r, _) = symmetricDifference in r *if* it turns out that this does not degrade performance. Cheers Ben From david.feuer at gmail.com Tue Dec 1 09:18:44 2020 From: david.feuer at gmail.com (David Feuer) Date: Tue, 1 Dec 2020 04:18:44 -0500 Subject: containers: symmetricDifference for Set and HashSet In-Reply-To: References: Message-ID: This has been raised before. I'm going to try to look at implementation within the next week or so. On Tue, Dec 1, 2020, 4:17 AM Ben Franksen wrote: > Would it make sense to add a function like the following to containers: > > symmetricDifference :: Set a -> Set a -> (Set a, Set a, Set a) > symmetricDifference a b = (a \\ b, a `intersection` b, b \\ a) > > with the idea that this can be implemented more efficiently as a > primitive than the above specification? (And similarly for HashSet.) > > If this is the case, then perhaps difference and intersection could be > defined in terms of this new primitive: > > difference a b = let (r, _, _) = symmetricDifference in r > intersection a b = let (_, r, _) = symmetricDifference in r > > *if* it turns out that this does not degrade performance. > > Cheers > Ben > > _______________________________________________ > 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 ben.franksen at online.de Tue Dec 1 09:33:57 2020 From: ben.franksen at online.de (Ben Franksen) Date: Tue, 1 Dec 2020 10:33:57 +0100 Subject: containers: symmetricDifference for Set and HashSet In-Reply-To: References: Message-ID: Thanks David! I wasn't aware this has been discussed before, though I should have expected it, given that the idea seems pretty obvious. BTW, something similar may be possible for Map and HashMap by adding an extra parameter that tells it how to combine values in the intersection. Cheers Ben Am 01.12.20 um 10:18 schrieb David Feuer: > This has been raised before. I'm going to try to look at implementation > within the next week or so. > > On Tue, Dec 1, 2020, 4:17 AM Ben Franksen wrote: > >> Would it make sense to add a function like the following to containers: >> >> symmetricDifference :: Set a -> Set a -> (Set a, Set a, Set a) >> symmetricDifference a b = (a \\ b, a `intersection` b, b \\ a) >> >> with the idea that this can be implemented more efficiently as a >> primitive than the above specification? (And similarly for HashSet.) >> >> If this is the case, then perhaps difference and intersection could be >> defined in terms of this new primitive: >> >> difference a b = let (r, _, _) = symmetricDifference in r >> intersection a b = let (_, r, _) = symmetricDifference in r >> >> *if* it turns out that this does not degrade performance. >> >> Cheers >> Ben >> >> _______________________________________________ >> 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 simon.jakobi at googlemail.com Tue Dec 1 09:33:56 2020 From: simon.jakobi at googlemail.com (Simon Jakobi) Date: Tue, 1 Dec 2020 10:33:56 +0100 Subject: containers: symmetricDifference for Set and HashSet In-Reply-To: References: Message-ID: A few months ago we briefly discussed a function with a slightly different type: symmetricDifference :: Set a -> Set a -> Set a symmetricDifference x y = (x \\ y) <> (y \\ x) See https://mail.haskell.org/pipermail/libraries/2020-June/030632.html. Am Di., 1. Dez. 2020 um 10:19 Uhr schrieb David Feuer : > > This has been raised before. I'm going to try to look at implementation within the next week or so. > > On Tue, Dec 1, 2020, 4:17 AM Ben Franksen wrote: >> >> Would it make sense to add a function like the following to containers: >> >> symmetricDifference :: Set a -> Set a -> (Set a, Set a, Set a) >> symmetricDifference a b = (a \\ b, a `intersection` b, b \\ a) >> >> with the idea that this can be implemented more efficiently as a >> primitive than the above specification? (And similarly for HashSet.) >> >> If this is the case, then perhaps difference and intersection could be >> defined in terms of this new primitive: >> >> difference a b = let (r, _, _) = symmetricDifference in r >> intersection a b = let (_, r, _) = symmetricDifference in r >> >> *if* it turns out that this does not degrade performance. >> >> Cheers >> Ben >> >> _______________________________________________ >> 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 andreas.abel at ifi.lmu.de Tue Dec 1 18:35:14 2020 From: andreas.abel at ifi.lmu.de (Andreas Abel) Date: Tue, 1 Dec 2020 19:35:14 +0100 Subject: containers: symmetricDifference for Set and HashSet In-Reply-To: References: Message-ID: <725b74e7-78ed-0e25-b30d-4ee2f73c4803@ifi.lmu.de> > symmetricDifference :: Set a -> Set a -> (Set a, Set a, Set a) Since projections from a 3-tuples are not in base (why?, one could wonder), I plea for a telling result name that helps confusing these three outputs. Something like data SymmetricDifference = SymmetricDifference { symDiffLeft :: Set a , symDiffCommon :: Set a , symDiffRight :: Set a } (Also fixing the problem of absent projections.) On 2020-12-01 10:16, Ben Franksen wrote: > Would it make sense to add a function like the following to containers: > > symmetricDifference :: Set a -> Set a -> (Set a, Set a, Set a) > symmetricDifference a b = (a \\ b, a `intersection` b, b \\ a) > > with the idea that this can be implemented more efficiently as a > primitive than the above specification? (And similarly for HashSet.) > > If this is the case, then perhaps difference and intersection could be > defined in terms of this new primitive: > > difference a b = let (r, _, _) = symmetricDifference in r > intersection a b = let (_, r, _) = symmetricDifference in r > > *if* it turns out that this does not degrade performance. > > Cheers > Ben > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From reedmullanix at gmail.com Sun Dec 6 06:20:02 2020 From: reedmullanix at gmail.com (Reed Mullanix) Date: Sat, 5 Dec 2020 22:20:02 -0800 Subject: containers: intersections for Set, along with Semigroup newtype Message-ID: Hey all, I've found myself reaching for the following function a couple of times now, so I figured it might make a good addition. intersections :: Ord a => NonEmpty (Set a) -> Set a intersections (s :| ss) = Foldable.foldl' intersection s ss In a similar vein, we may as well add the following newtype + instance combo: newtype Intersection a = Intersection { getIntersection :: Set a } instance (Ord a) => Semigroup (Intersection a) where (Intersection a) <> (Intersection b) = Intersection $ intersection a b stimes = stimesIdempotent Would love to hear everyone's thoughts on this! Thanks Reed Mullanix -------------- next part -------------- An HTML attachment was scrubbed... URL: From godzbanebane at gmail.com Sun Dec 6 07:40:15 2020 From: godzbanebane at gmail.com (Georgi Lyubenov) Date: Sun, 6 Dec 2020 09:40:15 +0200 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: +1 from me Seems like additional motivation for adding NonEmptyFoldable (or however people want to call it) ======= Georgi -------------- next part -------------- An HTML attachment was scrubbed... URL: From emilypi at cohomolo.gy Sun Dec 6 07:48:24 2020 From: emilypi at cohomolo.gy (Emily Pillmore) Date: Sun, 06 Dec 2020 07:48:24 +0000 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: Makes sense to me. On Sun, Dec 06, 2020 at 2:40 AM, Georgi Lyubenov < godzbanebane at gmail.com > wrote: > > +1 from me > > > Seems like additional motivation for adding NonEmptyFoldable (or however > people want to call it) > > > ======= > Georgi > > > _______________________________________________ > Libraries mailing list > Libraries@ haskell. org ( Libraries at haskell.org ) > http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries ) > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From martijn at hmbastiaan.nl Sun Dec 6 16:19:23 2020 From: martijn at hmbastiaan.nl (Martijn Bastiaan) Date: Sun, 6 Dec 2020 17:19:23 +0100 Subject: Proposal for containers: Add 'pop' function to Data.Map Message-ID: Hi all, Proposal:   * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`.   * See https://github.com/haskell/containers/pull/757 for exact definition Why:   * They're useful functions I expected to be in `Data.Map` and     `Data.IntMap`. (This might be influenced by the fact that     they're defined on Python's `dict`.)   * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`)     are harder to parse than a simple `pop`, which should help Haskell     codebases become a bit cleaner :).   * Their implementations are a bit non-obvious. My first instinct was     to write `(Map.lookup ..., Map.delete ...)`, which would have done     two traversals. Having "properly" implemented functions in the lib     would prevent people from writing their own suboptimal ones. Details and implementation:   * https://github.com/haskell/containers/pull/757 Kind regards, Martijn Bastiaan From david.feuer at gmail.com Sun Dec 6 16:25:33 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 11:25:33 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: The name pop makes me think of a stack. Is this use of the word common? On Sun, Dec 6, 2020, 11:20 AM Martijn Bastiaan via Libraries < libraries at haskell.org> wrote: > Hi all, > > Proposal: > > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. > * See https://github.com/haskell/containers/pull/757 for exact > definition > > Why: > > * They're useful functions I expected to be in `Data.Map` and > `Data.IntMap`. (This might be influenced by the fact that > they're defined on Python's `dict`.) > > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) > are harder to parse than a simple `pop`, which should help Haskell > codebases become a bit cleaner :). > > * Their implementations are a bit non-obvious. My first instinct was > to write `(Map.lookup ..., Map.delete ...)`, which would have done > two traversals. Having "properly" implemented functions in the lib > would prevent people from writing their own suboptimal ones. > > Details and implementation: > > * https://github.com/haskell/containers/pull/757 > > Kind regards, > Martijn Bastiaan > _______________________________________________ > 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 tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Sun Dec 6 16:25:54 2020 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Sun, 6 Dec 2020 16:25:54 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: <20201206162554.GD31165@cloudinit-builder> On Sun, Dec 06, 2020 at 05:19:23PM +0100, Martijn Bastiaan via Libraries wrote: > Proposal: > >   * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >   * See https://github.com/haskell/containers/pull/757 for exact definition Thanks. I wanted this recently! I contented myself with a lookup/delete pair but your efficient implementation would be better. From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Sun Dec 6 16:29:45 2020 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Sun, 6 Dec 2020 16:29:45 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: <20201206162945.GE31165@cloudinit-builder> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: > The name pop makes me think of a stack. Is this use of the word common? Python uses that name, which is why I'm familiar with it: >>> d = {'a': 1, 'b': 2} >>> d.pop('b') 2 >>> d {'a': 1} From martijn at hmbastiaan.nl Sun Dec 6 16:40:40 2020 From: martijn at hmbastiaan.nl (Martijn Bastiaan) Date: Sun, 6 Dec 2020 17:40:40 +0100 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <20201206162945.GE31165@cloudinit-builder> References: <20201206162945.GE31165@cloudinit-builder> Message-ID: <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other examples, but Java, Rust, and Ruby don't seem to offer `pop`-like functions for their (hash)maps. On 12/6/20 5:29 PM, Tom Ellis wrote: > On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >> The name pop makes me think of a stack. Is this use of the word common? > Python uses that name, which is why I'm familiar with it: > >>>> d = {'a': 1, 'b': 2} >>>> d.pop('b') > 2 >>>> d > {'a': 1} > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From david.feuer at gmail.com Sun Dec 6 16:43:58 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 11:43:58 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Message-ID: I suggest you add a version for Data.Sequence combining lookup with deleteAt. I wanted that for something fairly recently. On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < libraries at haskell.org> wrote: > Yeah, Python's `pop` made me call it `pop`. I had hoped to find other > examples, but Java, Rust, and Ruby don't seem to offer `pop`-like > functions for their (hash)maps. > > On 12/6/20 5:29 PM, Tom Ellis wrote: > > On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: > >> The name pop makes me think of a stack. Is this use of the word common? > > Python uses that name, which is why I'm familiar with it: > > > >>>> d = {'a': 1, 'b': 2} > >>>> d.pop('b') > > 2 > >>>> d > > {'a': 1} > > _______________________________________________ > > 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 carter.schonwald at gmail.com Sun Dec 6 17:16:55 2020 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Sun, 6 Dec 2020 12:16:55 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Message-ID: LookupThenRemove seems like a more descriptive name. Though I guess I can see why pop has appeal. On Sun, Dec 6, 2020 at 11:44 AM David Feuer wrote: > I suggest you add a version for Data.Sequence combining lookup with > deleteAt. I wanted that for something fairly recently. > > On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < > libraries at haskell.org> wrote: > >> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other >> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like >> functions for their (hash)maps. >> >> On 12/6/20 5:29 PM, Tom Ellis wrote: >> > On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >> >> The name pop makes me think of a stack. Is this use of the word common? >> > Python uses that name, which is why I'm familiar with it: >> > >> >>>> d = {'a': 1, 'b': 2} >> >>>> d.pop('b') >> > 2 >> >>>> d >> > {'a': 1} >> > _______________________________________________ >> > 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 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Sun Dec 6 17:25:29 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 12:25:29 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Message-ID: Or lookupRemove? Or possibly lookupAndRemove? The name pop will be confusing in Data.Sequence. On Sun, Dec 6, 2020, 12:17 PM Carter Schonwald wrote: > LookupThenRemove seems like a more descriptive name. Though I guess I can > see why pop has appeal. > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer wrote: > >> I suggest you add a version for Data.Sequence combining lookup with >> deleteAt. I wanted that for something fairly recently. >> >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < >> libraries at haskell.org> wrote: >> >>> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other >>> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like >>> functions for their (hash)maps. >>> >>> On 12/6/20 5:29 PM, Tom Ellis wrote: >>> > On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >>> >> The name pop makes me think of a stack. Is this use of the word >>> common? >>> > Python uses that name, which is why I'm familiar with it: >>> > >>> >>>> d = {'a': 1, 'b': 2} >>> >>>> d.pop('b') >>> > 2 >>> >>>> d >>> > {'a': 1} >>> > _______________________________________________ >>> > 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 >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From alexey at kuleshevi.ch Sun Dec 6 17:29:40 2020 From: alexey at kuleshevi.ch (Alexey Kuleshevich) Date: Sun, 06 Dec 2020 17:29:40 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Message-ID: `extract` is the name that I would suggest. I also agree with David that `pop` is a bit too confusing in a non-stack/queue data structure. If all languages named it pop, then it would be good argument for the name, but we don't need to copy python. The only thing that pyhon has that I wish we had in Haskell is the popularity ;) +1 on the function itself from me, I've needed it multiple occasions. ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ On Sunday, December 6, 2020 8:16 PM, Carter Schonwald wrote: > LookupThenRemove seems like a more descriptive name. Though I guess I can see why pop has appeal. > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer wrote: > >> I suggest you add a version for Data.Sequence combining lookup with deleteAt. I wanted that for something fairly recently. >> >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries wrote: >> >>> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other >>> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like >>> functions for their (hash)maps. >>> >>> On 12/6/20 5:29 PM, Tom Ellis wrote: >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >>>>> The name pop makes me think of a stack. Is this use of the word common? >>>> Python uses that name, which is why I'm familiar with it: >>>> >>>>>>> d = {'a': 1, 'b': 2} >>>>>>> d.pop('b') >>>> 2 >>>>>>> d >>>> {'a': 1} >>>> _______________________________________________ >>>> 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 -------------- next part -------------- An HTML attachment was scrubbed... URL: From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Sun Dec 6 17:34:21 2020 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Sun, 6 Dec 2020 17:34:21 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Message-ID: <20201206173421.GA2478@cloudinit-builder> I really like `extract`! On Sun, Dec 06, 2020 at 05:29:40PM +0000, Alexey Kuleshevich wrote: > `extract` is the name that I would suggest. I also agree with David > that `pop` is a bit too confusing in a non-stack/queue data > structure. If all languages named it pop, then it would be good > argument for the name, but we don't need to copy python. The only > thing that pyhon has that I wish we had in Haskell is the popularity > ;) > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald wrote: > > > LookupThenRemove seems like a more descriptive name. Though I guess I can see why pop has appeal. > > > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer wrote: > > > >> I suggest you add a version for Data.Sequence combining lookup with deleteAt. I wanted that for something fairly recently. > >> > >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries wrote: > >> > >>> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other > >>> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like > >>> functions for their (hash)maps. > >>> > >>> On 12/6/20 5:29 PM, Tom Ellis wrote: > >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: > >>>>> The name pop makes me think of a stack. Is this use of the word common? > >>>> Python uses that name, which is why I'm familiar with it: > >>>> > >>>>>>> d = {'a': 1, 'b': 2} > >>>>>>> d.pop('b') > >>>> 2 > >>>>>>> d > >>>> {'a': 1} > >>>> _______________________________________________ > >>>> 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 > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From bob at redivi.com Sun Dec 6 17:59:14 2020 From: bob at redivi.com (Bob Ippolito) Date: Sun, 6 Dec 2020 09:59:14 -0800 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <20201206173421.GA2478@cloudinit-builder> References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> <20201206173421.GA2478@cloudinit-builder> Message-ID: `extract` overlaps with the Comonad typeclass (extract, duplicate, extend) On Sun, Dec 6, 2020 at 9:34 AM Tom Ellis < tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: > I really like `extract`! > > On Sun, Dec 06, 2020 at 05:29:40PM +0000, Alexey Kuleshevich wrote: > > `extract` is the name that I would suggest. I also agree with David > > that `pop` is a bit too confusing in a non-stack/queue data > > structure. If all languages named it pop, then it would be good > > argument for the name, but we don't need to copy python. The only > > thing that pyhon has that I wish we had in Haskell is the popularity > > ;) > > > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ > > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald < > carter.schonwald at gmail.com> wrote: > > > > > LookupThenRemove seems like a more descriptive name. Though I guess I > can see why pop has appeal. > > > > > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer > wrote: > > > > > >> I suggest you add a version for Data.Sequence combining lookup with > deleteAt. I wanted that for something fairly recently. > > >> > > >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < > libraries at haskell.org> wrote: > > >> > > >>> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other > > >>> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like > > >>> functions for their (hash)maps. > > >>> > > >>> On 12/6/20 5:29 PM, Tom Ellis wrote: > > >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: > > >>>>> The name pop makes me think of a stack. Is this use of the word > common? > > >>>> Python uses that name, which is why I'm familiar with it: > > >>>> > > >>>>>>> d = {'a': 1, 'b': 2} > > >>>>>>> d.pop('b') > > >>>> 2 > > >>>>>>> d > > >>>> {'a': 1} > > >>>> _______________________________________________ > > >>>> 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 > > > _______________________________________________ > > 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 Sun Dec 6 18:02:13 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 13:02:13 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> <20201206173421.GA2478@cloudinit-builder> Message-ID: None of these types are comonads, so it doesn't seem *that* confusing. On Sun, Dec 6, 2020, 12:59 PM Bob Ippolito wrote: > `extract` overlaps with the Comonad typeclass (extract, duplicate, extend) > > On Sun, Dec 6, 2020 at 9:34 AM Tom Ellis < > tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: > >> I really like `extract`! >> >> On Sun, Dec 06, 2020 at 05:29:40PM +0000, Alexey Kuleshevich wrote: >> > `extract` is the name that I would suggest. I also agree with David >> > that `pop` is a bit too confusing in a non-stack/queue data >> > structure. If all languages named it pop, then it would be good >> > argument for the name, but we don't need to copy python. The only >> > thing that pyhon has that I wish we had in Haskell is the popularity >> > ;) >> > >> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ >> > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald < >> carter.schonwald at gmail.com> wrote: >> > >> > > LookupThenRemove seems like a more descriptive name. Though I guess I >> can see why pop has appeal. >> > > >> > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer >> wrote: >> > > >> > >> I suggest you add a version for Data.Sequence combining lookup with >> deleteAt. I wanted that for something fairly recently. >> > >> >> > >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < >> libraries at haskell.org> wrote: >> > >> >> > >>> Yeah, Python's `pop` made me call it `pop`. I had hoped to find >> other >> > >>> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like >> > >>> functions for their (hash)maps. >> > >>> >> > >>> On 12/6/20 5:29 PM, Tom Ellis wrote: >> > >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >> > >>>>> The name pop makes me think of a stack. Is this use of the word >> common? >> > >>>> Python uses that name, which is why I'm familiar with it: >> > >>>> >> > >>>>>>> d = {'a': 1, 'b': 2} >> > >>>>>>> d.pop('b') >> > >>>> 2 >> > >>>>>>> d >> > >>>> {'a': 1} >> > >>>> _______________________________________________ >> > >>>> 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 >> >> > _______________________________________________ >> > 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 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From a.pelenitsyn at gmail.com Sun Dec 6 17:22:35 2020 From: a.pelenitsyn at gmail.com (Artem Pelenitsyn) Date: Sun, 6 Dec 2020 12:22:35 -0500 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? Message-ID: Dear Libraries, I noticed the Numeric module has special-cased functions to read and show integral types in bases 8, 10, 16 but not for base 2. There are also generic-over-base versions, so an interested client can implement the special case for base 2 themselves with little hassle. Still, I think base 2 is common enough that we could support it along with base 8, 10, 16 out of the box. What do you think? I'm happy to submit a merge request if you concur. Kind regards, Artem Pelenitsyn -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Sun Dec 6 18:04:30 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 13:04:30 -0500 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: Agreed! On Sun, Dec 6, 2020, 1:03 PM Artem Pelenitsyn wrote: > Dear Libraries, > > I noticed the Numeric module has special-cased functions to read and show > integral types in bases 8, 10, 16 but not for base 2. There are also > generic-over-base versions, so an interested client can implement the > special case for base 2 themselves with little hassle. Still, I think base > 2 is common enough that we could support it along with base 8, 10, 16 out > of the box. > > What do you think? I'm happy to submit a merge request if you concur. > > Kind regards, > Artem Pelenitsyn > _______________________________________________ > 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 oleg.grenrus at iki.fi Sun Dec 6 18:04:58 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Sun, 6 Dec 2020 20:04:58 +0200 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> <20201206173421.GA2478@cloudinit-builder> Message-ID: <567643ae-697a-55f4-d67f-d4c792a5e1aa@iki.fi> NonEmptySeq could be. NonEmptySet almost (it could have extract). - Oleg On 6.12.2020 20.02, David Feuer wrote: > None of these types are comonads, so it doesn't seem *that* confusing. > > On Sun, Dec 6, 2020, 12:59 PM Bob Ippolito > wrote: > > `extract` overlaps with the Comonad typeclass (extract, duplicate, > extend) > > On Sun, Dec 6, 2020 at 9:34 AM Tom Ellis > > wrote: > > I really like `extract`! > > On Sun, Dec 06, 2020 at 05:29:40PM +0000, Alexey Kuleshevich > wrote: > > `extract` is the name that I would suggest. I also agree > with David > > that `pop` is a bit too confusing in a non-stack/queue data > > structure. If all languages named it pop, then it would be good > > argument for the name, but we don't need to copy python. The > only > > thing that pyhon has that I wish we had in Haskell is the > popularity > > ;) > > > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ > > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald > > wrote: > > > > > LookupThenRemove seems like a more descriptive name. > Though I guess I can see why pop has appeal. > > > > > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer > > wrote: > > > > > >> I suggest you add a version for Data.Sequence combining > lookup with deleteAt. I wanted that for something fairly recently. > > >> > > >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via > Libraries > wrote: > > >> > > >>> Yeah, Python's `pop` made me call it `pop`. I had hoped > to find other > > >>> examples, but Java, Rust, and Ruby don't seem to offer > `pop`-like > > >>> functions for their (hash)maps. > > >>> > > >>> On 12/6/20 5:29 PM, Tom Ellis wrote: > > >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer > wrote: > > >>>>> The name pop makes me think of a stack. Is this use of > the word common? > > >>>> Python uses that name, which is why I'm familiar with it: > > >>>> > > >>>>>>> d = {'a': 1, 'b': 2} > > >>>>>>> d.pop('b') > > >>>> 2 > > >>>>>>> d > > >>>> {'a': 1} > > >>>> _______________________________________________ > > >>>> 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 > > > _______________________________________________ > > 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 > > > _______________________________________________ > 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 Sun Dec 6 18:06:10 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 13:06:10 -0500 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: In particular, I tend to want to print something out in base 2 when I'm fussing around with bit twiddling. The last thing I want to be thinking about at that point is writing a showing function. On Sun, Dec 6, 2020, 1:03 PM Artem Pelenitsyn wrote: > Dear Libraries, > > I noticed the Numeric module has special-cased functions to read and show > integral types in bases 8, 10, 16 but not for base 2. There are also > generic-over-base versions, so an interested client can implement the > special case for base 2 themselves with little hassle. Still, I think base > 2 is common enough that we could support it along with base 8, 10, 16 out > of the box. > > What do you think? I'm happy to submit a merge request if you concur. > > Kind regards, > Artem Pelenitsyn > _______________________________________________ > 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 oleg.grenrus at iki.fi Sun Dec 6 18:06:16 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Sun, 6 Dec 2020 20:06:16 +0200 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: +1 On 6.12.2020 20.04, David Feuer wrote: > Agreed! > > On Sun, Dec 6, 2020, 1:03 PM Artem Pelenitsyn > wrote: > > Dear Libraries, > > I noticed the Numeric module has special-cased functions to read > and show integral types in bases 8, 10, 16 but not for base 2. > There are also generic-over-base versions, so an interested client > can implement the special case for base 2 themselves with little > hassle. Still, I think base 2 is common enough that we could > support it along with base 8, 10, 16 out of the box. > > What do you think? I'm happy to submit a merge request if you concur. > > Kind regards, > Artem Pelenitsyn > _______________________________________________ > 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 chessai1996 at gmail.com Sun Dec 6 18:10:54 2020 From: chessai1996 at gmail.com (chessai) Date: Sun, 6 Dec 2020 12:10:54 -0600 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: +1 On Sun, Dec 6, 2020, 12:07 Oleg Grenrus wrote: > +1 > On 6.12.2020 20.04, David Feuer wrote: > > Agreed! > > On Sun, Dec 6, 2020, 1:03 PM Artem Pelenitsyn > wrote: > >> Dear Libraries, >> >> I noticed the Numeric module has special-cased functions to read and show >> integral types in bases 8, 10, 16 but not for base 2. There are also >> generic-over-base versions, so an interested client can implement the >> special case for base 2 themselves with little hassle. Still, I think base >> 2 is common enough that we could support it along with base 8, 10, 16 out >> of the box. >> >> What do you think? I'm happy to submit a merge request if you concur. >> >> Kind regards, >> Artem Pelenitsyn >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > > _______________________________________________ > Libraries mailing listLibraries at haskell.orghttp://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 Sun Dec 6 18:26:18 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 13:26:18 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <567643ae-697a-55f4-d67f-d4c792a5e1aa@iki.fi> References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> <20201206173421.GA2478@cloudinit-builder> <567643ae-697a-55f4-d67f-d4c792a5e1aa@iki.fi> Message-ID: I guess the real point is that I don't think most people will expect an `extract` function in `containers` to be a comonadic one. On Sun, Dec 6, 2020, 1:05 PM Oleg Grenrus wrote: > NonEmptySeq could be. NonEmptySet almost (it could have extract). > > - Oleg > On 6.12.2020 20.02, David Feuer wrote: > > None of these types are comonads, so it doesn't seem *that* confusing. > > On Sun, Dec 6, 2020, 12:59 PM Bob Ippolito wrote: > >> `extract` overlaps with the Comonad typeclass (extract, duplicate, extend) >> >> On Sun, Dec 6, 2020 at 9:34 AM Tom Ellis < >> tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: >> >>> I really like `extract`! >>> >>> On Sun, Dec 06, 2020 at 05:29:40PM +0000, Alexey Kuleshevich wrote: >>> > `extract` is the name that I would suggest. I also agree with David >>> > that `pop` is a bit too confusing in a non-stack/queue data >>> > structure. If all languages named it pop, then it would be good >>> > argument for the name, but we don't need to copy python. The only >>> > thing that pyhon has that I wish we had in Haskell is the popularity >>> > ;) >>> > >>> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ >>> > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald < >>> carter.schonwald at gmail.com> wrote: >>> > >>> > > LookupThenRemove seems like a more descriptive name. Though I guess >>> I can see why pop has appeal. >>> > > >>> > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer >>> wrote: >>> > > >>> > >> I suggest you add a version for Data.Sequence combining lookup with >>> deleteAt. I wanted that for something fairly recently. >>> > >> >>> > >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < >>> libraries at haskell.org> wrote: >>> > >> >>> > >>> Yeah, Python's `pop` made me call it `pop`. I had hoped to find >>> other >>> > >>> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like >>> > >>> functions for their (hash)maps. >>> > >>> >>> > >>> On 12/6/20 5:29 PM, Tom Ellis wrote: >>> > >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >>> > >>>>> The name pop makes me think of a stack. Is this use of the word >>> common? >>> > >>>> Python uses that name, which is why I'm familiar with it: >>> > >>>> >>> > >>>>>>> d = {'a': 1, 'b': 2} >>> > >>>>>>> d.pop('b') >>> > >>>> 2 >>> > >>>>>>> d >>> > >>>> {'a': 1} >>> > >>>> _______________________________________________ >>> > >>>> 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 >>> >>> > _______________________________________________ >>> > 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 >> > > _______________________________________________ > Libraries mailing listLibraries at haskell.orghttp://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 alexandreR_B at outlook.com Sun Dec 6 18:27:18 2020 From: alexandreR_B at outlook.com (=?iso-8859-1?Q?Alexandre_Rodrigues_Bald=E9?=) Date: Sun, 6 Dec 2020 18:27:18 +0000 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: Sounds like a good idea, could it be possible to use a typeclass instead of `NonEmpty (Set a)`? I recall needing this a few times, but not over a NonEmpty. De: Libraries em nome de Reed Mullanix Enviado: Sunday, December 6, 2020 6:20:02 AM Para: Haskell Libraries Assunto: containers: intersections for Set, along with Semigroup newtype Hey all, I've found myself reaching for the following function a couple of times now, so I figured it might make a good addition. intersections :: Ord a => NonEmpty (Set a) -> Set a intersections (s :| ss) = Foldable.foldl' intersection s ss In a similar vein, we may as well add the following newtype + instance combo: newtype Intersection a = Intersection { getIntersection :: Set a } instance (Ord a) => Semigroup (Intersection a) where (Intersection a) <> (Intersection b) = Intersection $ intersection a b stimes = stimesIdempotent Would love to hear everyone's thoughts on this! Thanks Reed Mullanix -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 77ADE3F8A9834F68A968FAB2DFD72243.png Type: image/png Size: 159 bytes Desc: 77ADE3F8A9834F68A968FAB2DFD72243.png URL: From andreas.abel at ifi.lmu.de Sun Dec 6 18:38:11 2020 From: andreas.abel at ifi.lmu.de (Andreas Abel) Date: Sun, 6 Dec 2020 19:38:11 +0100 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <567643ae-697a-55f4-d67f-d4c792a5e1aa@iki.fi> References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> <20201206173421.GA2478@cloudinit-builder> <567643ae-697a-55f4-d67f-d4c792a5e1aa@iki.fi> Message-ID: <9602678f-58cc-090a-4508-aed05c84bde9@ifi.lmu.de> I have reservations against this proposal: 1. `pop` seems to be below the Fairbairn threshold. > pop :: Int -> IntMap a -> (Maybe a, IntMap a) > pop = updateLookupWithKey (\_ _ -> Nothing) It specializes the Swiss knife `updateLookupWithKey` without involving any other map-specific function. 2. Addition of `pop` would require a similar function in all other standard collections, to keep their interfaces in sync. 3. Is there sufficient evidence that `pop` is a strongly user-demanded feature? One way to quantify this is to look on hackage for the pattern `updateLookupWithKey (\_ _ -> Nothing)` (and variants) and maybe even on how often this pattern has been given a name. (The latter would be a more scientific way to develop our libraries in general. Instead of randomly adding functionality based on non-representative discussions on this list, we could scan hackage for common patterns---especially, mine popular utility libraries. Harvest the intelligence of the masses...) While I would not recommend to add `pop`, I would recommend to enhance the documentation of `updateLookupWithKey` to include `pop` as a use case. This would also ensure the discoverability of the present solution. I seem to recall that we have given this recommendation to similar proposals in the past ("similar" in terms of the Fairbairn threshold). Cheers, Andreas On 2020-12-06 19:04, Oleg Grenrus wrote: > NonEmptySeq could be. NonEmptySet almost (it could have extract). > > - Oleg > > On 6.12.2020 20.02, David Feuer wrote: >> None of these types are comonads, so it doesn't seem *that* confusing. >> >> On Sun, Dec 6, 2020, 12:59 PM Bob Ippolito > > wrote: >> >> `extract` overlaps with the Comonad typeclass (extract, duplicate, >> extend) >> >> On Sun, Dec 6, 2020 at 9:34 AM Tom Ellis >> > > wrote: >> >> I really like `extract`! >> >> On Sun, Dec 06, 2020 at 05:29:40PM +0000, Alexey Kuleshevich >> wrote: >> > `extract` is the name that I would suggest. I also agree >> with David >> > that `pop` is a bit too confusing in a non-stack/queue data >> > structure. If all languages named it pop, then it would be good >> > argument for the name, but we don't need to copy python. The >> only >> > thing that pyhon has that I wish we had in Haskell is the >> popularity >> > ;) >> > >> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ >> > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald >> > > wrote: >> > >> > > LookupThenRemove seems like a more descriptive name. >> Though I guess I can see why pop has appeal. >> > > >> > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer >> > wrote: >> > > >> > >> I suggest you add a version for Data.Sequence combining >> lookup with deleteAt. I wanted that for something fairly recently. >> > >> >> > >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via >> Libraries > > wrote: >> > >> >> > >>> Yeah, Python's `pop` made me call it `pop`. I had hoped >> to find other >> > >>> examples, but Java, Rust, and Ruby don't seem to offer >> `pop`-like >> > >>> functions for their (hash)maps. >> > >>> >> > >>> On 12/6/20 5:29 PM, Tom Ellis wrote: >> > >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer >> wrote: >> > >>>>> The name pop makes me think of a stack. Is this use of >> the word common? >> > >>>> Python uses that name, which is why I'm familiar with it: >> > >>>> >> > >>>>>>> d = {'a': 1, 'b': 2} >> > >>>>>>> d.pop('b') >> > >>>> 2 >> > >>>>>>> d >> > >>>> {'a': 1} >> > >>>> _______________________________________________ >> > >>>> 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 >> >> >> > _______________________________________________ >> > 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 >> >> >> >> _______________________________________________ >> 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 reedmullanix at gmail.com Sun Dec 6 18:41:13 2020 From: reedmullanix at gmail.com (Reed Mullanix) Date: Sun, 6 Dec 2020 10:41:13 -0800 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: In a perfect world we would use something like Foldable1 from semigroupoids, but sadly that is not in base. However, this is exactly why I proposed the Intersection newtype, as it would make it nice and easy to use with a Foldable1 like type class. On Sun, Dec 6, 2020 at 10:27 AM Alexandre Rodrigues Baldé < alexandreR_B at outlook.com> wrote: > Sounds like a good idea, could it be possible to use a typeclass instead > of `NonEmpty (Set a)`? > > I recall needing this a few times, but not over a NonEmpty. > > > > *De:* Libraries em nome de Reed Mullanix < > reedmullanix at gmail.com> > *Enviado:* Sunday, December 6, 2020 6:20:02 AM > *Para:* Haskell Libraries > *Assunto:* containers: intersections for Set, along with Semigroup newtype > > > > Hey all, > > I've found myself reaching for the following function a couple of times > now, so I figured it might make a good addition. > > > > intersections :: Ord a => NonEmpty (Set a) -> Set a > intersections (s :| ss) = Foldable.foldl' intersection s ss > > > > In a similar vein, we may as well add the following newtype + instance > combo: > > > > newtype Intersection a = Intersection { getIntersection :: Set a } > > > > instance (Ord a) => Semigroup (Intersection a) where > (Intersection a) <> (Intersection b) = Intersection $ intersection a > b > stimes = stimesIdempotent > > > > Would love to hear everyone's thoughts on this! > > Thanks > > Reed Mullanix > -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 77ADE3F8A9834F68A968FAB2DFD72243.png Type: image/png Size: 159 bytes Desc: not available URL: From svenpanne at gmail.com Sun Dec 6 18:50:13 2020 From: svenpanne at gmail.com (Sven Panne) Date: Sun, 6 Dec 2020 19:50:13 +0100 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: Am So., 6. Dez. 2020 um 07:20 Uhr schrieb Reed Mullanix < reedmullanix at gmail.com>: > [...] > intersections :: Ord a => NonEmpty (Set a) -> Set a > intersections (s :| ss) = Foldable.foldl' intersection s ss > [...] > Why NonEmpty? I would expect "intersections [] = Set.empty", because the result contains all the elements which are in all sets, i.e. none. That's at least my intuition, is there some law which this would violate? -------------- next part -------------- An HTML attachment was scrubbed... URL: From reedmullanix at gmail.com Sun Dec 6 18:55:59 2020 From: reedmullanix at gmail.com (Reed Mullanix) Date: Sun, 6 Dec 2020 10:55:59 -0800 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: It doesn't violate any laws per say, due to the general lawlessness of Foldable, but violates aesthetics. If we restrict it to NonEmpty then we get a lovely semigroup homomorphism! If we loosen it to lists, then the identity element of the list monoid gets mapped to an absorbing element in the Set semigroup under intersection, which just feels... off. On Sun, Dec 6, 2020 at 10:50 AM Sven Panne wrote: > Am So., 6. Dez. 2020 um 07:20 Uhr schrieb Reed Mullanix < > reedmullanix at gmail.com>: > >> [...] >> intersections :: Ord a => NonEmpty (Set a) -> Set a >> intersections (s :| ss) = Foldable.foldl' intersection s ss >> [...] >> > > Why NonEmpty? I would expect "intersections [] = Set.empty", because the > result contains all the elements which are in all sets, i.e. none. That's > at least my intuition, is there some law which this would violate? > -------------- next part -------------- An HTML attachment was scrubbed... URL: From emertens at gmail.com Sun Dec 6 18:58:24 2020 From: emertens at gmail.com (Eric Mertens) Date: Sun, 6 Dec 2020 10:58:24 -0800 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: <44DF2D9D-8252-4AD8-B694-925DB417084F@gmail.com> First consider how `and` and `or` work for booleans. and (x ++ y) == and x && and y For this to work we need `and [] == True` or (x ++ y) == or x || or y For this to work we need `or [] == False` and and or are duals of each other. There’s an analogue here to union and intersection which are also duals of each other. We have: unions (x ++ y) == union (unions x) (unions y) This requires `union [] == []` since any list xs could be split as `[] ++ xs` We'd like to have: intersections (x ++ y) == intersect (intersections x) (intersections y) For this kind of splitting property to make sense for intersections we’d need `intersections [] == listOfAllElementsOfThisType`, but it’s not easy to construct that list of all elements in general. So instead we punt on the problem and refuse to define intersections on an empty list. -glguy > On Dec 6, 2020, at 10:50 AM, Sven Panne wrote: > > Am So., 6. Dez. 2020 um 07:20 Uhr schrieb Reed Mullanix >: > [...] > intersections :: Ord a => NonEmpty (Set a) -> Set a > intersections (s :| ss) = Foldable.foldl' intersection s ss > [...] > > Why NonEmpty? I would expect "intersections [] = Set.empty", because the result contains all the elements which are in all sets, i.e. none. That's at least my intuition, is there some law which this would violate? > _______________________________________________ > 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 svenpanne at gmail.com Sun Dec 6 18:58:53 2020 From: svenpanne at gmail.com (Sven Panne) Date: Sun, 6 Dec 2020 19:58:53 +0100 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: Am So., 6. Dez. 2020 um 19:56 Uhr schrieb Reed Mullanix < reedmullanix at gmail.com>: > It doesn't violate any laws per say, due to the general lawlessness of > Foldable, but violates aesthetics. [...] > To me it's just the other way around: It violates aesthetics if it doesn't follow the mathematical definition in all cases, which is why I don't like NonEmpty here. > -------------- next part -------------- An HTML attachment was scrubbed... URL: From godzbanebane at gmail.com Sun Dec 6 19:01:03 2020 From: godzbanebane at gmail.com (Georgi Lyubenov) Date: Sun, 6 Dec 2020 21:01:03 +0200 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: I would be opposed to intersections [] = [] as it is true that *all* things have the property of being a member of every element of []. In set theory without classes I've usually seen this worked around by never using intersections on an empty set (ie using NonEmpty) ======= Georgi -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Sun Dec 6 19:01:18 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 14:01:18 -0500 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: intersections [] = empty is unacceptable to me. The options that make sense to me are the nonempty (ideally Foldable1) one, one producing a Maybe, and I guess even one that throws an error on an empty list (ouch). On Sun, Dec 6, 2020, 1:50 PM Sven Panne wrote: > Am So., 6. Dez. 2020 um 07:20 Uhr schrieb Reed Mullanix < > reedmullanix at gmail.com>: > >> [...] >> intersections :: Ord a => NonEmpty (Set a) -> Set a >> intersections (s :| ss) = Foldable.foldl' intersection s ss >> [...] >> > > Why NonEmpty? I would expect "intersections [] = Set.empty", because the > result contains all the elements which are in all sets, i.e. none. That's > at least my intuition, is there some law which this would violate? > _______________________________________________ > 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 emilypi at cohomolo.gy Sun Dec 6 19:01:33 2020 From: emilypi at cohomolo.gy (Emily Pillmore) Date: Sun, 06 Dec 2020 19:01:33 +0000 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: +1 On Sun, Dec 06, 2020 at 1:10 PM, chessai < chessai1996 at gmail.com > wrote: > > +1 > > On Sun, Dec 6, 2020, 12:07 Oleg Grenrus < oleg. grenrus@ iki. fi ( > oleg.grenrus at iki.fi ) > wrote: > > >> >> >> +1 >> >> >> On 6.12.2020 20.04, David Feuer wrote: >> >> >>> Agreed! >>> >>> On Sun, Dec 6, 2020, 1:03 PM Artem Pelenitsyn < a. pelenitsyn@ gmail. com ( >>> a.pelenitsyn at gmail.com ) > wrote: >>> >>> >>>> Dear Libraries, >>>> >>>> >>>> I noticed the Numeric module has special-cased functions to read and show >>>> integral types in bases 8, 10, 16 but not for base 2. There are also >>>> generic-over-base versions, so an interested client can implement the >>>> special case for base 2 themselves with little hassle. Still, I think base >>>> 2 is common enough that we could support it along with base 8, 10, 16 out >>>> of the box. >>>> >>>> >>>> >>>> What do you think? I'm happy to submit a merge request if you concur. >>>> >>>> >>>> Kind regards, >>>> Artem Pelenitsyn >>>> >>>> _______________________________________________ >>>> Libraries mailing list >>>> Libraries@ haskell. org ( Libraries at haskell.org ) >>>> http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries ) >>>> >>> >>> >>> >>> _______________________________________________ >>> Libraries mailing list >>> Libraries@ haskell. org ( Libraries at haskell.org ) >>> http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries ) >>> >> >> >> _______________________________________________ >> Libraries mailing list >> Libraries@ haskell. org ( Libraries at haskell.org ) >> http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries ) >> > > > > > _______________________________________________ > Libraries mailing list > Libraries@ haskell. org ( Libraries at haskell.org ) > http:/ / mail. haskell. org/ cgi-bin/ mailman/ listinfo/ libraries ( > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries ) > > > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Sun Dec 6 19:06:02 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sun, 6 Dec 2020 20:06:02 +0100 (CET) Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: On Sun, 6 Dec 2020, Emily Pillmore wrote: > +1 > > On Sun, Dec 06, 2020 at 1:10 PM, chessai wrote: > +1 > > On Sun, Dec 6, 2020, 12:07 Oleg Grenrus wrote: > > +1 Base 2 +1 +1 +1 = Base 5 - Is this, what we want? From philip.hazelden at gmail.com Sun Dec 6 19:05:55 2020 From: philip.hazelden at gmail.com (Philip Hazelden) Date: Sun, 6 Dec 2020 19:05:55 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Message-ID: I don't love `extract`, myself. I can see the motivation - extracting something generally means removing it without destroying it. But I worry that that's not salient enough to make the meaning clear. I dunno, maybe it's just that Data.Map already has "update", "alter" and "adjust", and I have no idea which is which - I don't think extract would be as bad as those, but it feels like in the same direction. For the Maybe version, I'd suggest `deleteLookup`. Or at least something with both those words, but this combination seems to be what I'd expect given the existing `splitLookup`, `deleteFindMin` and `deleteFindMax`. "delete" seems to be the standard "remove something from the map" - the word "remove" isn't yet used, so I don't see any reason to introduce it. And "lookup" seems to be the standard name for "look something up using Maybe in case it's not there". (By contrast, "find" seems to be the standard name for "look something up and error if it's not there".) For the default version, the only existing function I can see that takes a default is `findWithDefault`. (And this is the only use of "find" in the name of a function that doesn't error.) `deleteFindWithDefault` is a handful, but it would still be my suggestion. On Sun, Dec 6, 2020 at 5:30 PM Alexey Kuleshevich wrote: > `extract` is the name that I would suggest. I also agree with David that > `pop` is a bit too confusing in a non-stack/queue data structure. If all > languages named it pop, then it would be good argument for the name, but we > don't need to copy python. The only thing that pyhon has that I wish we had > in Haskell is the popularity ;) > +1 on the function itself from me, I've needed it multiple occasions. > > > > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald < > carter.schonwald at gmail.com> wrote: > > LookupThenRemove seems like a more descriptive name. Though I guess I can > see why pop has appeal. > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer wrote: > >> I suggest you add a version for Data.Sequence combining lookup with >> deleteAt. I wanted that for something fairly recently. >> >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < >> libraries at haskell.org> wrote: >> >>> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other >>> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like >>> functions for their (hash)maps. >>> >>> On 12/6/20 5:29 PM, Tom Ellis wrote: >>> > On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >>> >> The name pop makes me think of a stack. Is this use of the word >>> common? >>> > Python uses that name, which is why I'm familiar with it: >>> > >>> >>>> d = {'a': 1, 'b': 2} >>> >>>> d.pop('b') >>> > 2 >>> >>>> d >>> > {'a': 1} >>> > _______________________________________________ >>> > 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 >> > > _______________________________________________ > 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 simon.jakobi at googlemail.com Sun Dec 6 19:41:06 2020 From: simon.jakobi at googlemail.com (Simon Jakobi) Date: Sun, 6 Dec 2020 20:41:06 +0100 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: Regarding the type signature: pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) I think it might be better to be consistent with similar functions like minView :: Map k a -> Maybe (a, Map k a) and uncons :: [a] -> Maybe (a, [a]) Therefore the type should be pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) --- I like the "pop" name though – I think the analogy to stacks is pretty obvious. --- Like Andreas Abel I believe, that if there is a good, simple implementation, it might be a good first step to simply document the implementation as an example. If there's much demand for exporting the function or if a fast implementation is more complex, we can still enhance the API later on. Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via Libraries : > > Hi all, > > Proposal: > > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. > * See https://github.com/haskell/containers/pull/757 for exact definition > > Why: > > * They're useful functions I expected to be in `Data.Map` and > `Data.IntMap`. (This might be influenced by the fact that > they're defined on Python's `dict`.) > > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) > are harder to parse than a simple `pop`, which should help Haskell > codebases become a bit cleaner :). > > * Their implementations are a bit non-obvious. My first instinct was > to write `(Map.lookup ..., Map.delete ...)`, which would have done > two traversals. Having "properly" implemented functions in the lib > would prevent people from writing their own suboptimal ones. > > Details and implementation: > > * https://github.com/haskell/containers/pull/757 > > Kind regards, > Martijn Bastiaan > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From tikhon at jelv.is Sun Dec 6 20:09:02 2020 From: tikhon at jelv.is (Tikhon Jelvis) Date: Sun, 6 Dec 2020 12:09:02 -0800 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: Absolutely agree on this. I've needed to render a number in binary a couple of times, and each time I had to stop and think about how to use showIntAtBase. It's not hard per se, but it is really fiddly. The expression I end up using is hard to understand at a glance and uses a scary-looking (but safe-ish) partial function: showIntAtBase 2 ("01" !!) x "" A dedicated function is a clear improvement, although the ShowS bit is still unnecessarily fiddly for use outside implementing Show instances: showBinary x "" To be honest, I really don't like the Numeric module at all. I use hex a bit more often than binary, but I just do it with printf. I was going to suggest adding %b to printf alongside this change, but it looks like Text.Printf already supports it! So while I think adding showBinary absolutely makes sense, I'll probably just use printf myself going forwards. On Sun, Dec 6, 2020 at 11:06 AM Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Sun, 6 Dec 2020, Emily Pillmore wrote: > > > +1 > > > > On Sun, Dec 06, 2020 at 1:10 PM, chessai wrote: > > +1 > > > > On Sun, Dec 6, 2020, 12:07 Oleg Grenrus wrote: > > > > +1 > > > Base 2 +1 +1 +1 = Base 5 - Is this, what we want? > _______________________________________________ > 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 martijn at hmbastiaan.nl Sun Dec 6 20:25:16 2020 From: martijn at hmbastiaan.nl (Martijn Bastiaan) Date: Sun, 6 Dec 2020 21:25:16 +0100 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> Message-ID: <477029c9-fb28-99c8-3171-0519d16de73a@hmbastiaan.nl> I've taken a look, and it seems like a non-trivial change. For now I've added a version that simply traverses two times for Seq, to have API parity with Map/IntMap. If people are happy to accept pop/popWithDefault (be it with different names) I'll put in the work to make it do a single traversal for Seq too. On 12/6/20 5:43 PM, David Feuer wrote: > I suggest you add a version for Data.Sequence combining lookup with > deleteAt. I wanted that for something fairly recently. > > On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries > > wrote: > > Yeah, Python's `pop` made me call it `pop`. I had hoped to find other > examples, but Java, Rust, and Ruby don't seem to offer `pop`-like > functions for their (hash)maps. > > On 12/6/20 5:29 PM, Tom Ellis wrote: > > On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: > >> The name pop makes me think of a stack. Is this use of the word > common? > > Python uses that name, which is why I'm familiar with it: > > > >>>> d = {'a': 1, 'b': 2} > >>>> d.pop('b') > > 2 > >>>> d > > {'a': 1} > > _______________________________________________ > > 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 Sun Dec 6 20:32:44 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 15:32:44 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <477029c9-fb28-99c8-3171-0519d16de73a@hmbastiaan.nl> References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> <477029c9-fb28-99c8-3171-0519d16de73a@hmbastiaan.nl> Message-ID: I wrote deleteAt, so I could probably write this function somewhat more easily than anyone else, once it has a name. On Sun, Dec 6, 2020, 3:25 PM Martijn Bastiaan wrote: > I've taken a look, and it seems like a non-trivial change. For now I've > added a version that simply traverses two times for Seq, to have API parity > with Map/IntMap. If people are happy to accept pop/popWithDefault (be it > with different names) I'll put in the work to make it do a single traversal > for Seq too. > On 12/6/20 5:43 PM, David Feuer wrote: > > I suggest you add a version for Data.Sequence combining lookup with > deleteAt. I wanted that for something fairly recently. > > On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via Libraries < > libraries at haskell.org> wrote: > >> Yeah, Python's `pop` made me call it `pop`. I had hoped to find other >> examples, but Java, Rust, and Ruby don't seem to offer `pop`-like >> functions for their (hash)maps. >> >> On 12/6/20 5:29 PM, Tom Ellis wrote: >> > On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer wrote: >> >> The name pop makes me think of a stack. Is this use of the word common? >> > Python uses that name, which is why I'm familiar with it: >> > >> >>>> d = {'a': 1, 'b': 2} >> >>>> d.pop('b') >> > 2 >> >>>> d >> > {'a': 1} >> > _______________________________________________ >> > 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 Sun Dec 6 21:25:39 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 16:25:39 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: I want the Maybe on the outside if we do this at all. On Sun, Dec 6, 2020, 11:20 AM Martijn Bastiaan via Libraries < libraries at haskell.org> wrote: > Hi all, > > Proposal: > > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. > * See https://github.com/haskell/containers/pull/757 for exact > definition > > Why: > > * They're useful functions I expected to be in `Data.Map` and > `Data.IntMap`. (This might be influenced by the fact that > they're defined on Python's `dict`.) > > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) > are harder to parse than a simple `pop`, which should help Haskell > codebases become a bit cleaner :). > > * Their implementations are a bit non-obvious. My first instinct was > to write `(Map.lookup ..., Map.delete ...)`, which would have done > two traversals. Having "properly" implemented functions in the lib > would prevent people from writing their own suboptimal ones. > > Details and implementation: > > * https://github.com/haskell/containers/pull/757 > > Kind regards, > Martijn Bastiaan > _______________________________________________ > 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 carter.schonwald at gmail.com Sun Dec 6 21:37:15 2020 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Sun, 6 Dec 2020 16:37:15 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <9602678f-58cc-090a-4508-aed05c84bde9@ifi.lmu.de> References: <20201206162945.GE31165@cloudinit-builder> <3bd936c7-4fd6-6af6-ddc0-da9f73231f53@hmbastiaan.nl> <20201206173421.GA2478@cloudinit-builder> <567643ae-697a-55f4-d67f-d4c792a5e1aa@iki.fi> <9602678f-58cc-090a-4508-aed05c84bde9@ifi.lmu.de> Message-ID: Well said Andreas, I emphatically agree with your latter point: We need to ground proposal need / utility with statistical information about actual code out in the world. On Sun, Dec 6, 2020 at 1:38 PM Andreas Abel wrote: > I have reservations against this proposal: > > 1. `pop` seems to be below the Fairbairn threshold. > > > pop :: Int -> IntMap a -> (Maybe a, IntMap a) > > pop = updateLookupWithKey (\_ _ -> Nothing) > > It specializes the Swiss knife `updateLookupWithKey` without involving > any other map-specific function. > > 2. Addition of `pop` would require a similar function in all other > standard collections, to keep their interfaces in sync. > > 3. Is there sufficient evidence that `pop` is a strongly user-demanded > feature? One way to quantify this is to look on hackage for the pattern > `updateLookupWithKey (\_ _ -> Nothing)` (and variants) and maybe even on > how often this pattern has been given a name. > > (The latter would be a more scientific way to develop our libraries in > general. Instead of randomly adding functionality based on > non-representative discussions on this list, we could scan hackage for > common patterns---especially, mine popular utility libraries. Harvest > the intelligence of the masses...) > > While I would not recommend to add `pop`, I would recommend to enhance > the documentation of `updateLookupWithKey` to include `pop` as a use > case. This would also ensure the discoverability of the present solution. > > I seem to recall that we have given this recommendation to similar > proposals in the past ("similar" in terms of the Fairbairn threshold). > > Cheers, > Andreas > > On 2020-12-06 19:04, Oleg Grenrus wrote: > > NonEmptySeq could be. NonEmptySet almost (it could have extract). > > > > - Oleg > > > > On 6.12.2020 20.02, David Feuer wrote: > >> None of these types are comonads, so it doesn't seem *that* confusing. > >> > >> On Sun, Dec 6, 2020, 12:59 PM Bob Ippolito >> > wrote: > >> > >> `extract` overlaps with the Comonad typeclass (extract, duplicate, > >> extend) > >> > >> On Sun, Dec 6, 2020 at 9:34 AM Tom Ellis > >> >> > wrote: > >> > >> I really like `extract`! > >> > >> On Sun, Dec 06, 2020 at 05:29:40PM +0000, Alexey Kuleshevich > >> wrote: > >> > `extract` is the name that I would suggest. I also agree > >> with David > >> > that `pop` is a bit too confusing in a non-stack/queue data > >> > structure. If all languages named it pop, then it would be > good > >> > argument for the name, but we don't need to copy python. The > >> only > >> > thing that pyhon has that I wish we had in Haskell is the > >> popularity > >> > ;) > >> > > >> > ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐ > >> > On Sunday, December 6, 2020 8:16 PM, Carter Schonwald > >> >> > wrote: > >> > > >> > > LookupThenRemove seems like a more descriptive name. > >> Though I guess I can see why pop has appeal. > >> > > > >> > > On Sun, Dec 6, 2020 at 11:44 AM David Feuer > >> > wrote: > >> > > > >> > >> I suggest you add a version for Data.Sequence combining > >> lookup with deleteAt. I wanted that for something fairly > recently. > >> > >> > >> > >> On Sun, Dec 6, 2020, 11:41 AM Martijn Bastiaan via > >> Libraries >> > wrote: > >> > >> > >> > >>> Yeah, Python's `pop` made me call it `pop`. I had hoped > >> to find other > >> > >>> examples, but Java, Rust, and Ruby don't seem to offer > >> `pop`-like > >> > >>> functions for their (hash)maps. > >> > >>> > >> > >>> On 12/6/20 5:29 PM, Tom Ellis wrote: > >> > >>>> On Sun, Dec 06, 2020 at 11:25:33AM -0500, David Feuer > >> wrote: > >> > >>>>> The name pop makes me think of a stack. Is this use of > >> the word common? > >> > >>>> Python uses that name, which is why I'm familiar with it: > >> > >>>> > >> > >>>>>>> d = {'a': 1, 'b': 2} > >> > >>>>>>> d.pop('b') > >> > >>>> 2 > >> > >>>>>>> d > >> > >>>> {'a': 1} > >> > >>>> _______________________________________________ > >> > >>>> 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 > >> > >> > >> > _______________________________________________ > >> > 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 > >> > >> > >> > >> _______________________________________________ > >> 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 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg.grenrus at iki.fi Sun Dec 6 22:33:56 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Mon, 7 Dec 2020 00:33:56 +0200 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: <895bda23-c7db-0444-2e8a-6f55d44ed3cb@iki.fi> so it's uninsert (re uncons). - Oleg On 6.12.2020 21.41, Simon Jakobi via Libraries wrote: > Regarding the type signature: > > pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) > > I think it might be better to be consistent with similar functions like > > minView :: Map k a -> Maybe (a, Map k a) > > and > > uncons :: [a] -> Maybe (a, [a]) > > Therefore the type should be > > pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) > > --- > > I like the "pop" name though – I think the analogy to stacks is pretty obvious. > > --- > > Like Andreas Abel I believe, that if there is a good, simple > implementation, it might be a good first step to simply document the > implementation as an example. > > If there's much demand for exporting the function or if a fast > implementation is more complex, we can still enhance the API later on. > > > Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via > Libraries : >> Hi all, >> >> Proposal: >> >> * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >> * See https://github.com/haskell/containers/pull/757 for exact definition >> >> Why: >> >> * They're useful functions I expected to be in `Data.Map` and >> `Data.IntMap`. (This might be influenced by the fact that >> they're defined on Python's `dict`.) >> >> * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) >> are harder to parse than a simple `pop`, which should help Haskell >> codebases become a bit cleaner :). >> >> * Their implementations are a bit non-obvious. My first instinct was >> to write `(Map.lookup ..., Map.delete ...)`, which would have done >> two traversals. Having "properly" implemented functions in the lib >> would prevent people from writing their own suboptimal ones. >> >> Details and implementation: >> >> * https://github.com/haskell/containers/pull/757 >> >> Kind regards, >> Martijn Bastiaan >> _______________________________________________ >> 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 philip.hazelden at gmail.com Sun Dec 6 22:58:21 2020 From: philip.hazelden at gmail.com (Philip Hazelden) Date: Sun, 6 Dec 2020 22:58:21 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: Hm. I note that with `minView` and `uncons`, moving the Maybe to the inside doesn't increase the space of return values. That is, any input that gives `Nothing` now would give `(Nothing, empty)` if Maybe was on the inside. That's not true of this function; if the key isn't found, that doesn't tell us what is in the map. Of course it tells us that the second part of the return value is the same as the input map, but that feels not super-close to "the second part of the return value is this one specific value". And, my sense is that having Maybe on the inside would be more often what people would want to use. Like... if you don't care what the map-without-this-element looks like, you'd just use lookup. So clearly the caller of this function is going to use it in some cases. Maybe-on-the-outside is fine if you'll use it "only if the element was already there", but seems likely awkward otherwise. So I'd argue for keeping the Maybe on the inside. On Sun, Dec 6, 2020 at 7:42 PM Simon Jakobi via Libraries < libraries at haskell.org> wrote: > Regarding the type signature: > > pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) > > I think it might be better to be consistent with similar functions like > > minView :: Map k a -> Maybe (a, Map k a) > > and > > uncons :: [a] -> Maybe (a, [a]) > > Therefore the type should be > > pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) > > --- > > I like the "pop" name though – I think the analogy to stacks is pretty > obvious. > > --- > > Like Andreas Abel I believe, that if there is a good, simple > implementation, it might be a good first step to simply document the > implementation as an example. > > If there's much demand for exporting the function or if a fast > implementation is more complex, we can still enhance the API later on. > > > Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via > Libraries : > > > > Hi all, > > > > Proposal: > > > > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. > > * See https://github.com/haskell/containers/pull/757 for exact > definition > > > > Why: > > > > * They're useful functions I expected to be in `Data.Map` and > > `Data.IntMap`. (This might be influenced by the fact that > > they're defined on Python's `dict`.) > > > > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) > > are harder to parse than a simple `pop`, which should help Haskell > > codebases become a bit cleaner :). > > > > * Their implementations are a bit non-obvious. My first instinct was > > to write `(Map.lookup ..., Map.delete ...)`, which would have done > > two traversals. Having "properly" implemented functions in the lib > > would prevent people from writing their own suboptimal ones. > > > > Details and implementation: > > > > * https://github.com/haskell/containers/pull/757 > > > > Kind regards, > > Martijn Bastiaan > > _______________________________________________ > > 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 Sun Dec 6 23:30:15 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 18:30:15 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: It feels very awkward to me. On Sun, Dec 6, 2020, 5:59 PM Philip Hazelden wrote: > Hm. I note that with `minView` and `uncons`, moving the Maybe to the > inside doesn't increase the space of return values. That is, any input that > gives `Nothing` now would give `(Nothing, empty)` if Maybe was on the > inside. That's not true of this function; if the key isn't found, that > doesn't tell us what is in the map. Of course it tells us that the second > part of the return value is the same as the input map, but that feels not > super-close to "the second part of the return value is this one specific > value". > > And, my sense is that having Maybe on the inside would be more often what > people would want to use. Like... if you don't care what the > map-without-this-element looks like, you'd just use lookup. So clearly the > caller of this function is going to use it in some cases. > Maybe-on-the-outside is fine if you'll use it "only if the element was > already there", but seems likely awkward otherwise. > > So I'd argue for keeping the Maybe on the inside. > > On Sun, Dec 6, 2020 at 7:42 PM Simon Jakobi via Libraries < > libraries at haskell.org> wrote: > >> Regarding the type signature: >> >> pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) >> >> I think it might be better to be consistent with similar functions like >> >> minView :: Map k a -> Maybe (a, Map k a) >> >> and >> >> uncons :: [a] -> Maybe (a, [a]) >> >> Therefore the type should be >> >> pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) >> >> --- >> >> I like the "pop" name though – I think the analogy to stacks is pretty >> obvious. >> >> --- >> >> Like Andreas Abel I believe, that if there is a good, simple >> implementation, it might be a good first step to simply document the >> implementation as an example. >> >> If there's much demand for exporting the function or if a fast >> implementation is more complex, we can still enhance the API later on. >> >> >> Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via >> Libraries : >> > >> > Hi all, >> > >> > Proposal: >> > >> > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >> > * See https://github.com/haskell/containers/pull/757 for exact >> definition >> > >> > Why: >> > >> > * They're useful functions I expected to be in `Data.Map` and >> > `Data.IntMap`. (This might be influenced by the fact that >> > they're defined on Python's `dict`.) >> > >> > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) >> > are harder to parse than a simple `pop`, which should help Haskell >> > codebases become a bit cleaner :). >> > >> > * Their implementations are a bit non-obvious. My first instinct was >> > to write `(Map.lookup ..., Map.delete ...)`, which would have done >> > two traversals. Having "properly" implemented functions in the lib >> > would prevent people from writing their own suboptimal ones. >> > >> > Details and implementation: >> > >> > * https://github.com/haskell/containers/pull/757 >> > >> > Kind regards, >> > Martijn Bastiaan >> > _______________________________________________ >> > 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 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From keith.wygant at gmail.com Mon Dec 7 00:24:46 2020 From: keith.wygant at gmail.com (Keith) Date: Mon, 07 Dec 2020 00:24:46 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: <3C432771-79BD-476A-AE34-4E43F35D5F39@gmail.com> Think of it as 'pop' again. Your state is the Map. You return Maybe the deleted value and a new state of the Map with the value (maybe) deleted. It makes no sense for your new state to be an empty Map (Nothing) when the key wasn't in the map. — Sent from my phone with K-9 Mail. On December 6, 2020 11:30:15 PM UTC, David Feuer wrote: >It feels very awkward to me. > >On Sun, Dec 6, 2020, 5:59 PM Philip Hazelden >wrote: > >> Hm. I note that with `minView` and `uncons`, moving the Maybe to the >> inside doesn't increase the space of return values. That is, any input that >> gives `Nothing` now would give `(Nothing, empty)` if Maybe was on the >> inside. That's not true of this function; if the key isn't found, that >> doesn't tell us what is in the map. Of course it tells us that the second >> part of the return value is the same as the input map, but that feels not >> super-close to "the second part of the return value is this one specific >> value". >> >> And, my sense is that having Maybe on the inside would be more often what >> people would want to use. Like... if you don't care what the >> map-without-this-element looks like, you'd just use lookup. So clearly the >> caller of this function is going to use it in some cases. >> Maybe-on-the-outside is fine if you'll use it "only if the element was >> already there", but seems likely awkward otherwise. >> >> So I'd argue for keeping the Maybe on the inside. >> >> On Sun, Dec 6, 2020 at 7:42 PM Simon Jakobi via Libraries < >> libraries at haskell.org> wrote: >> >>> Regarding the type signature: >>> >>> pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) >>> >>> I think it might be better to be consistent with similar functions like >>> >>> minView :: Map k a -> Maybe (a, Map k a) >>> >>> and >>> >>> uncons :: [a] -> Maybe (a, [a]) >>> >>> Therefore the type should be >>> >>> pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) >>> >>> --- >>> >>> I like the "pop" name though – I think the analogy to stacks is pretty >>> obvious. >>> >>> --- >>> >>> Like Andreas Abel I believe, that if there is a good, simple >>> implementation, it might be a good first step to simply document the >>> implementation as an example. >>> >>> If there's much demand for exporting the function or if a fast >>> implementation is more complex, we can still enhance the API later on. >>> >>> >>> Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via >>> Libraries : >>> > >>> > Hi all, >>> > >>> > Proposal: >>> > >>> > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >>> > * See https://github.com/haskell/containers/pull/757 for exact >>> definition >>> > >>> > Why: >>> > >>> > * They're useful functions I expected to be in `Data.Map` and >>> > `Data.IntMap`. (This might be influenced by the fact that >>> > they're defined on Python's `dict`.) >>> > >>> > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) >>> > are harder to parse than a simple `pop`, which should help Haskell >>> > codebases become a bit cleaner :). >>> > >>> > * Their implementations are a bit non-obvious. My first instinct was >>> > to write `(Map.lookup ..., Map.delete ...)`, which would have done >>> > two traversals. Having "properly" implemented functions in the lib >>> > would prevent people from writing their own suboptimal ones. >>> > >>> > Details and implementation: >>> > >>> > * https://github.com/haskell/containers/pull/757 >>> > >>> > Kind regards, >>> > Martijn Bastiaan >>> > _______________________________________________ >>> > 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 >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From keith.wygant at gmail.com Mon Dec 7 00:30:39 2020 From: keith.wygant at gmail.com (Keith) Date: Mon, 07 Dec 2020 00:30:39 +0000 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: Also, I'm not sure if this is a real concern, but holding a reference to the original Map seems more likely to leak memory that always using the 'new' map returned by 'popWithKey'. — Sent from my phone with K-9 Mail. On December 6, 2020 11:30:15 PM UTC, David Feuer wrote: >It feels very awkward to me. > >On Sun, Dec 6, 2020, 5:59 PM Philip Hazelden >wrote: > >> Hm. I note that with `minView` and `uncons`, moving the Maybe to the >> inside doesn't increase the space of return values. That is, any input that >> gives `Nothing` now would give `(Nothing, empty)` if Maybe was on the >> inside. That's not true of this function; if the key isn't found, that >> doesn't tell us what is in the map. Of course it tells us that the second >> part of the return value is the same as the input map, but that feels not >> super-close to "the second part of the return value is this one specific >> value". >> >> And, my sense is that having Maybe on the inside would be more often what >> people would want to use. Like... if you don't care what the >> map-without-this-element looks like, you'd just use lookup. So clearly the >> caller of this function is going to use it in some cases. >> Maybe-on-the-outside is fine if you'll use it "only if the element was >> already there", but seems likely awkward otherwise. >> >> So I'd argue for keeping the Maybe on the inside. >> >> On Sun, Dec 6, 2020 at 7:42 PM Simon Jakobi via Libraries < >> libraries at haskell.org> wrote: >> >>> Regarding the type signature: >>> >>> pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) >>> >>> I think it might be better to be consistent with similar functions like >>> >>> minView :: Map k a -> Maybe (a, Map k a) >>> >>> and >>> >>> uncons :: [a] -> Maybe (a, [a]) >>> >>> Therefore the type should be >>> >>> pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) >>> >>> --- >>> >>> I like the "pop" name though – I think the analogy to stacks is pretty >>> obvious. >>> >>> --- >>> >>> Like Andreas Abel I believe, that if there is a good, simple >>> implementation, it might be a good first step to simply document the >>> implementation as an example. >>> >>> If there's much demand for exporting the function or if a fast >>> implementation is more complex, we can still enhance the API later on. >>> >>> >>> Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via >>> Libraries : >>> > >>> > Hi all, >>> > >>> > Proposal: >>> > >>> > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >>> > * See https://github.com/haskell/containers/pull/757 for exact >>> definition >>> > >>> > Why: >>> > >>> > * They're useful functions I expected to be in `Data.Map` and >>> > `Data.IntMap`. (This might be influenced by the fact that >>> > they're defined on Python's `dict`.) >>> > >>> > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) >>> > are harder to parse than a simple `pop`, which should help Haskell >>> > codebases become a bit cleaner :). >>> > >>> > * Their implementations are a bit non-obvious. My first instinct was >>> > to write `(Map.lookup ..., Map.delete ...)`, which would have done >>> > two traversals. Having "properly" implemented functions in the lib >>> > would prevent people from writing their own suboptimal ones. >>> > >>> > Details and implementation: >>> > >>> > * https://github.com/haskell/containers/pull/757 >>> > >>> > Kind regards, >>> > Martijn Bastiaan >>> > _______________________________________________ >>> > 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 >> -------------- next part -------------- An HTML attachment was scrubbed... URL: From casper at unbc.ca Mon Dec 7 00:46:55 2020 From: casper at unbc.ca (David Casperson) Date: Sun, 6 Dec 2020 16:46:55 -0800 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: Intersection is a lattice operation, whose identity element is the "whole universe" not the empty set. Imagine if we had an intersections :: [Set a] -> Set a we would expect it have the law intersections (a ++ b) = (intersections a) `intersect` (intersections b) now let b be [] and aa == intersections a, and we get aa == aa `intersect` (intersections []) and this must hold for all aa, which is impossible unless we have some kind of universe set. David -- David Casperson, PhD, R.P., | David.Casperson at unbc.ca Associate Professor and Chair, | (250) 960-6672 Fax 960-5544 Computer Science | 3333 University Way University of Northern British Columbia | Prince George, BC V2N 4Z9 | CANADA Sven Panne, on 2020-12-06, you wrote: > From: Sven Panne > To: Reed Mullanix > Date: Sun, 6 Dec 2020 10:50:13 > Cc: Haskell Libraries > Subject: Re: containers: intersections for Set, along with Semigroup newtype > Message-ID: > > > > CAUTION: This email is not from UNBC. Avoid links and attachments. Don't buy gift cards. > > Am So., 6. Dez. 2020 um 07:20 Uhr schrieb Reed Mullanix : > [...] >   intersections :: Ord a => NonEmpty (Set a) -> Set a >   intersections (s :| ss) = Foldable.foldl' intersection s ss > [...] > > > Why NonEmpty? I would expect "intersections [] = Set.empty", because the result contains all the elements which are > in all sets, i.e. none. That's at least my intuition, is there some law which this would violate? > > -------------- next part -------------- _______________________________________________ Libraries mailing list Libraries at haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From david.feuer at gmail.com Mon Dec 7 02:02:00 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 21:02:00 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: Message-ID: That's not a concern. On Sun, Dec 6, 2020, 7:31 PM Keith wrote: > Also, I'm not sure if this is a real concern, but holding a reference to > the original Map seems more likely to leak memory that always using the > 'new' map returned by 'popWithKey'. > — > Sent from my phone with K-9 Mail. > > On December 6, 2020 11:30:15 PM UTC, David Feuer > wrote: >> >> It feels very awkward to me. >> >> On Sun, Dec 6, 2020, 5:59 PM Philip Hazelden >> wrote: >> >>> Hm. I note that with `minView` and `uncons`, moving the Maybe to the >>> inside doesn't increase the space of return values. That is, any input that >>> gives `Nothing` now would give `(Nothing, empty)` if Maybe was on the >>> inside. That's not true of this function; if the key isn't found, that >>> doesn't tell us what is in the map. Of course it tells us that the second >>> part of the return value is the same as the input map, but that feels not >>> super-close to "the second part of the return value is this one specific >>> value". >>> >>> And, my sense is that having Maybe on the inside would be more often >>> what people would want to use. Like... if you don't care what the >>> map-without-this-element looks like, you'd just use lookup. So clearly the >>> caller of this function is going to use it in some cases. >>> Maybe-on-the-outside is fine if you'll use it "only if the element was >>> already there", but seems likely awkward otherwise. >>> >>> So I'd argue for keeping the Maybe on the inside. >>> >>> On Sun, Dec 6, 2020 at 7:42 PM Simon Jakobi via Libraries < >>> libraries at haskell.org> wrote: >>> >>>> Regarding the type signature: >>>> >>>> pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) >>>> >>>> I think it might be better to be consistent with similar functions like >>>> >>>> minView :: Map k a -> Maybe (a, Map k a) >>>> >>>> and >>>> >>>> uncons :: [a] -> Maybe (a, [a]) >>>> >>>> Therefore the type should be >>>> >>>> pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) >>>> >>>> --- >>>> >>>> I like the "pop" name though – I think the analogy to stacks is pretty >>>> obvious. >>>> >>>> --- >>>> >>>> Like Andreas Abel I believe, that if there is a good, simple >>>> implementation, it might be a good first step to simply document the >>>> implementation as an example. >>>> >>>> If there's much demand for exporting the function or if a fast >>>> implementation is more complex, we can still enhance the API later on. >>>> >>>> >>>> Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via >>>> Libraries : >>>> > >>>> > Hi all, >>>> > >>>> > Proposal: >>>> > >>>> > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >>>> > * See https://github.com/haskell/containers/pull/757 for exact >>>> definition >>>> > >>>> > Why: >>>> > >>>> > * They're useful functions I expected to be in `Data.Map` and >>>> > `Data.IntMap`. (This might be influenced by the fact that >>>> > they're defined on Python's `dict`.) >>>> > >>>> > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) >>>> > are harder to parse than a simple `pop`, which should help >>>> Haskell >>>> > codebases become a bit cleaner :). >>>> > >>>> > * Their implementations are a bit non-obvious. My first instinct >>>> was >>>> > to write `(Map.lookup ..., Map.delete ...)`, which would have >>>> done >>>> > two traversals. Having "properly" implemented functions in the >>>> lib >>>> > would prevent people from writing their own suboptimal ones. >>>> > >>>> > Details and implementation: >>>> > >>>> > * https://github.com/haskell/containers/pull/757 >>>> > >>>> > Kind regards, >>>> > Martijn Bastiaan >>>> > _______________________________________________ >>>> > 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 >>> >> _______________________________________________ > 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 Mon Dec 7 02:06:57 2020 From: david.feuer at gmail.com (David Feuer) Date: Sun, 6 Dec 2020 21:06:57 -0500 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: <3C432771-79BD-476A-AE34-4E43F35D5F39@gmail.com> References: <3C432771-79BD-476A-AE34-4E43F35D5F39@gmail.com> Message-ID: That depends on whether you want State (Map k v) (Maybe v) or StateT (Map k v) Maybe v Both ideas are useful, but for a data structure library I believe the latter is more often what you want, and what more users will expect. The approach you suggest is redundant, and makes the type less informative. You have to read the documentation to know what map gets returned if the key isn't present. On Sun, Dec 6, 2020, 7:25 PM Keith wrote: > Think of it as 'pop' again. Your state is the Map. You return Maybe the > deleted value and a new state of the Map with the value (maybe) deleted. It > makes no sense for your new state to be an empty Map (Nothing) when the key > wasn't in the map. > — > Sent from my phone with K-9 Mail. > > On December 6, 2020 11:30:15 PM UTC, David Feuer > wrote: >> >> It feels very awkward to me. >> >> On Sun, Dec 6, 2020, 5:59 PM Philip Hazelden >> wrote: >> >>> Hm. I note that with `minView` and `uncons`, moving the Maybe to the >>> inside doesn't increase the space of return values. That is, any input that >>> gives `Nothing` now would give `(Nothing, empty)` if Maybe was on the >>> inside. That's not true of this function; if the key isn't found, that >>> doesn't tell us what is in the map. Of course it tells us that the second >>> part of the return value is the same as the input map, but that feels not >>> super-close to "the second part of the return value is this one specific >>> value". >>> >>> And, my sense is that having Maybe on the inside would be more often >>> what people would want to use. Like... if you don't care what the >>> map-without-this-element looks like, you'd just use lookup. So clearly the >>> caller of this function is going to use it in some cases. >>> Maybe-on-the-outside is fine if you'll use it "only if the element was >>> already there", but seems likely awkward otherwise. >>> >>> So I'd argue for keeping the Maybe on the inside. >>> >>> On Sun, Dec 6, 2020 at 7:42 PM Simon Jakobi via Libraries < >>> libraries at haskell.org> wrote: >>> >>>> Regarding the type signature: >>>> >>>> pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) >>>> >>>> I think it might be better to be consistent with similar functions like >>>> >>>> minView :: Map k a -> Maybe (a, Map k a) >>>> >>>> and >>>> >>>> uncons :: [a] -> Maybe (a, [a]) >>>> >>>> Therefore the type should be >>>> >>>> pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) >>>> >>>> --- >>>> >>>> I like the "pop" name though – I think the analogy to stacks is pretty >>>> obvious. >>>> >>>> --- >>>> >>>> Like Andreas Abel I believe, that if there is a good, simple >>>> implementation, it might be a good first step to simply document the >>>> implementation as an example. >>>> >>>> If there's much demand for exporting the function or if a fast >>>> implementation is more complex, we can still enhance the API later on. >>>> >>>> >>>> Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via >>>> Libraries : >>>> > >>>> > Hi all, >>>> > >>>> > Proposal: >>>> > >>>> > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >>>> > * See https://github.com/haskell/containers/pull/757 for exact >>>> definition >>>> > >>>> > Why: >>>> > >>>> > * They're useful functions I expected to be in `Data.Map` and >>>> > `Data.IntMap`. (This might be influenced by the fact that >>>> > they're defined on Python's `dict`.) >>>> > >>>> > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) >>>> > are harder to parse than a simple `pop`, which should help >>>> Haskell >>>> > codebases become a bit cleaner :). >>>> > >>>> > * Their implementations are a bit non-obvious. My first instinct >>>> was >>>> > to write `(Map.lookup ..., Map.delete ...)`, which would have >>>> done >>>> > two traversals. Having "properly" implemented functions in the >>>> lib >>>> > would prevent people from writing their own suboptimal ones. >>>> > >>>> > Details and implementation: >>>> > >>>> > * https://github.com/haskell/containers/pull/757 >>>> > >>>> > Kind regards, >>>> > Martijn Bastiaan >>>> > _______________________________________________ >>>> > 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 >>> >> _______________________________________________ > 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 Mon Dec 7 08:43:35 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 7 Dec 2020 09:43:35 +0100 (CET) Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: On Sun, 6 Dec 2020, Reed Mullanix wrote: > In a perfect world we would use something like Foldable1 from > semigroupoids, but sadly that is not in base. Is it necessary to have it in base for your use? For me, 'NonEmpty.foldl1 Set.intersection' is perfect. From david.feuer at gmail.com Mon Dec 7 08:50:05 2020 From: david.feuer at gmail.com (David Feuer) Date: Mon, 7 Dec 2020 03:50:05 -0500 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: That implementation doesn't short-circuit if the accumulator goes empty. It also relies on the optimizer to accumulate strictly. On Mon, Dec 7, 2020, 3:44 AM Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Sun, 6 Dec 2020, Reed Mullanix wrote: > > > In a perfect world we would use something like Foldable1 from > > semigroupoids, but sadly that is not in base. > > Is it necessary to have it in base for your use? For me, 'NonEmpty.foldl1 > Set.intersection' is perfect. > _______________________________________________ > 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 simon.jakobi at googlemail.com Mon Dec 7 22:18:59 2020 From: simon.jakobi at googlemail.com (Simon Jakobi) Date: Mon, 7 Dec 2020 23:18:59 +0100 Subject: Proposal for containers: Add 'pop' function to Data.Map In-Reply-To: References: <3C432771-79BD-476A-AE34-4E43F35D5F39@gmail.com> Message-ID: It would be enlightening to see some examples of how pop is intended to be used. After reading Philip's response I suspect that users might rather want > State (Map k v) (Maybe v) and that the Maybe should therefore be inside the tuple. Am Mo., 7. Dez. 2020 um 03:07 Uhr schrieb David Feuer : > > That depends on whether you want > > State (Map k v) (Maybe v) > > or > > StateT (Map k v) Maybe v > > Both ideas are useful, but for a data structure library I believe the latter is more often what you want, and what more users will expect. The approach you suggest is redundant, and makes the type less informative. You have to read the documentation to know what map gets returned if the key isn't present. > > On Sun, Dec 6, 2020, 7:25 PM Keith wrote: >> >> Think of it as 'pop' again. Your state is the Map. You return Maybe the deleted value and a new state of the Map with the value (maybe) deleted. It makes no sense for your new state to be an empty Map (Nothing) when the key wasn't in the map. >> — >> Sent from my phone with K-9 Mail. >> >> On December 6, 2020 11:30:15 PM UTC, David Feuer wrote: >>> >>> It feels very awkward to me. >>> >>> On Sun, Dec 6, 2020, 5:59 PM Philip Hazelden wrote: >>>> >>>> Hm. I note that with `minView` and `uncons`, moving the Maybe to the inside doesn't increase the space of return values. That is, any input that gives `Nothing` now would give `(Nothing, empty)` if Maybe was on the inside. That's not true of this function; if the key isn't found, that doesn't tell us what is in the map. Of course it tells us that the second part of the return value is the same as the input map, but that feels not super-close to "the second part of the return value is this one specific value". >>>> >>>> And, my sense is that having Maybe on the inside would be more often what people would want to use. Like... if you don't care what the map-without-this-element looks like, you'd just use lookup. So clearly the caller of this function is going to use it in some cases. Maybe-on-the-outside is fine if you'll use it "only if the element was already there", but seems likely awkward otherwise. >>>> >>>> So I'd argue for keeping the Maybe on the inside. >>>> >>>> On Sun, Dec 6, 2020 at 7:42 PM Simon Jakobi via Libraries wrote: >>>>> >>>>> Regarding the type signature: >>>>> >>>>> pop :: Ord k => k -> Map k a -> (Maybe a, Map k a) >>>>> >>>>> I think it might be better to be consistent with similar functions like >>>>> >>>>> minView :: Map k a -> Maybe (a, Map k a) >>>>> >>>>> and >>>>> >>>>> uncons :: [a] -> Maybe (a, [a]) >>>>> >>>>> Therefore the type should be >>>>> >>>>> pop :: Ord k => k -> Map k a -> Maybe (a, Map k a) >>>>> >>>>> --- >>>>> >>>>> I like the "pop" name though – I think the analogy to stacks is pretty obvious. >>>>> >>>>> --- >>>>> >>>>> Like Andreas Abel I believe, that if there is a good, simple >>>>> implementation, it might be a good first step to simply document the >>>>> implementation as an example. >>>>> >>>>> If there's much demand for exporting the function or if a fast >>>>> implementation is more complex, we can still enhance the API later on. >>>>> >>>>> >>>>> Am So., 6. Dez. 2020 um 17:20 Uhr schrieb Martijn Bastiaan via >>>>> Libraries : >>>>> > >>>>> > Hi all, >>>>> > >>>>> > Proposal: >>>>> > >>>>> > * Add `pop` and `popWithDefault` to `Data.Map` and `Data.IntMap`. >>>>> > * See https://github.com/haskell/containers/pull/757 for exact definition >>>>> > >>>>> > Why: >>>>> > >>>>> > * They're useful functions I expected to be in `Data.Map` and >>>>> > `Data.IntMap`. (This might be influenced by the fact that >>>>> > they're defined on Python's `dict`.) >>>>> > >>>>> > * Their implementations (~ `updateLookupWithKey (\_ _ -> Nothing)`) >>>>> > are harder to parse than a simple `pop`, which should help Haskell >>>>> > codebases become a bit cleaner :). >>>>> > >>>>> > * Their implementations are a bit non-obvious. My first instinct was >>>>> > to write `(Map.lookup ..., Map.delete ...)`, which would have done >>>>> > two traversals. Having "properly" implemented functions in the lib >>>>> > would prevent people from writing their own suboptimal ones. >>>>> > >>>>> > Details and implementation: >>>>> > >>>>> > * https://github.com/haskell/containers/pull/757 >>>>> > >>>>> > Kind regards, >>>>> > Martijn Bastiaan >>>>> > _______________________________________________ >>>>> > 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 >> >> _______________________________________________ >> 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 andrew.thaddeus at gmail.com Tue Dec 8 01:17:34 2020 From: andrew.thaddeus at gmail.com (Andrew Martin) Date: Mon, 7 Dec 2020 20:17:34 -0500 Subject: Numeric supports base 8, 10, 16 but not 2 -- why? In-Reply-To: References: Message-ID: I need binary encode/decode about once every six months, and I too find it annoying that these are missing. +1 from me. On Sun, Dec 6, 2020 at 3:09 PM Tikhon Jelvis wrote: > Absolutely agree on this. I've needed to render a number in binary a > couple of times, and each time I had to stop and think about how to use > showIntAtBase. It's not hard per se, but it is really fiddly. The > expression I end up using is hard to understand at a glance and uses a > scary-looking (but safe-ish) partial function: > > showIntAtBase 2 ("01" !!) x "" > > A dedicated function is a clear improvement, although the ShowS bit is > still unnecessarily fiddly for use outside implementing Show instances: > > showBinary x "" > > To be honest, I really don't like the Numeric module at all. I use hex a > bit more often than binary, but I just do it with printf. I was going to > suggest adding %b to printf alongside this change, but it looks like > Text.Printf already supports it! So while I think adding showBinary > absolutely makes sense, I'll probably just use printf myself going forwards. > > On Sun, Dec 6, 2020 at 11:06 AM Henning Thielemann < > lemming at henning-thielemann.de> wrote: > >> >> On Sun, 6 Dec 2020, Emily Pillmore wrote: >> >> > +1 >> > >> > On Sun, Dec 06, 2020 at 1:10 PM, chessai wrote: >> > +1 >> > >> > On Sun, Dec 6, 2020, 12:07 Oleg Grenrus wrote: >> > >> > +1 >> >> >> Base 2 +1 +1 +1 = Base 5 - Is this, what we want? >> _______________________________________________ >> 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 > -- -Andrew Thaddeus Martin -------------- next part -------------- An HTML attachment was scrubbed... URL: From reedmullanix at gmail.com Thu Dec 10 06:37:51 2020 From: reedmullanix at gmail.com (Reed Mullanix) Date: Wed, 9 Dec 2020 22:37:51 -0800 Subject: Proposal: Add 'Foldable1' to base Message-ID: With the recent discussion around the addition of 'intersection' to containers, I think it might be a good time to re-open the discussion surrounding adding 'Foldable1' to base. For context, 'Foldable1' would be a subclass of 'Foldable' that abstracts folds over non-empty containers. Alternatively, it can be seen as a method of combining together the elements of a container using a semigroup. The contents of this class have been discussed previously (See [1,2]), and the version presented in this proposal is taken from [1]. class Foldable t => Foldable1 t where {-# MINIMAL foldMap1 | foldr1map #-} fold1 :: Semigroup m => t m -> m -- the defining member, like foldMap but only asking for Semigroup foldMap1 :: Semigroup m => (a -> m) -> t a -> m -- strict foldMap1, cf foldMap' foldMap1' :: Semigroup m => (a -> m) -> t a -> m -- analogue of toList toNonEmpty :: t a -> NonEmpty a -- left&right, strict&non-strict folds foldr1 :: (a -> a -> a) -> t a -> a foldr1' :: (a -> a -> a) -> t a -> a foldl1 :: (a -> a -> a) -> t a -> a foldl1' :: (a -> a -> a) -> t a -> a -- these can have efficient implementation for NonEmptySet maximum1 :: Ord a => t a -> a minimum1 :: Ord a => t a -> a -- head1 have efficient implementation for NonEmpty and Tree -- last1 for symmetry head1 :: t a -> a last1 :: t a -> a -- fold variants with premap. -- Without this map, we cannot implement foldl using foldr etc. foldrMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b foldlMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b foldlMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b foldrMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b This has a couple of benefits. On the practical side, we can provide total alternatives to existing partial functions (IE: 'foldr1' and friends). It also enables us to fold over containers using a semigroup instance, which comes up suprisingly often. Naming: -------------------------------------------------------------------------------- Historically, the biggest source of controversy with this proposal has been over the name. The class currently exists in semigroupoids [3] under the name 'Foldable1', though there was some discussion around renaming it to 'SemiFoldable' [4]. However, if we keep the name unchanged, it makes the migration path nice and straightforward, and the possible name conflict with Data.Functor.Classes seems unlikely. Migration: -------------------------------------------------------------------------------- If we decide to go with 'Foldable1' as the name, we should be able to perform this change with 0 breakage. References: [1] https://mail.haskell.org/pipermail/libraries/2019-November/030059.html [2] https://gitlab.haskell.org/ghc/ghc/-/issues/13573 [3] https://hackage.haskell.org/package/semigroupoids-5.3.4/docs/Data-Semigroup-Foldable.html#t:Foldable1 [4] https://github.com/ekmett/semigroupoids/issues/26 From david.feuer at gmail.com Thu Dec 10 07:07:57 2020 From: david.feuer at gmail.com (David Feuer) Date: Thu, 10 Dec 2020 02:07:57 -0500 Subject: Proposal: Add 'Foldable1' to base In-Reply-To: References: Message-ID: That seems rather large to me, and some of those methods don't have much if any historical usage. I'd recommend starting with a slightly smaller class. It's always easier to add more later than to remove. My suggestion: foldMap1 :: Semigroup m => (a -> m) -> t a -> m foldMap1' :: Semigroup m => (a -> m) -> t a -> m toNonEmpty :: t a -> NonEmpty a The rest can be exported as functions, rather than methods, to begin with. On Thu, Dec 10, 2020, 1:38 AM Reed Mullanix wrote: > With the recent discussion around the addition of 'intersection' to > containers, > I think it might be a good time to re-open the discussion surrounding > adding > 'Foldable1' to base. > > For context, 'Foldable1' would be a subclass of 'Foldable' that abstracts > folds over non-empty containers. Alternatively, it can be seen as a method > of combining together the elements of a container using a semigroup. > The contents of this class have been discussed previously (See [1,2]), > and the version presented in this proposal is taken from [1]. > > class Foldable t => Foldable1 t where > {-# MINIMAL foldMap1 | foldr1map #-} > > fold1 :: Semigroup m => t m -> m > > -- the defining member, like foldMap but only asking for Semigroup > foldMap1 :: Semigroup m => (a -> m) -> t a -> m > > -- strict foldMap1, cf foldMap' > foldMap1' :: Semigroup m => (a -> m) -> t a -> m > > -- analogue of toList > toNonEmpty :: t a -> NonEmpty a > > -- left&right, strict&non-strict folds > foldr1 :: (a -> a -> a) -> t a -> a > foldr1' :: (a -> a -> a) -> t a -> a > foldl1 :: (a -> a -> a) -> t a -> a > foldl1' :: (a -> a -> a) -> t a -> a > > -- these can have efficient implementation for NonEmptySet > maximum1 :: Ord a => t a -> a > minimum1 :: Ord a => t a -> a > > -- head1 have efficient implementation for NonEmpty and Tree > -- last1 for symmetry > head1 :: t a -> a > last1 :: t a -> a > > -- fold variants with premap. > -- Without this map, we cannot implement foldl using foldr etc. > foldrMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b > foldlMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b > foldlMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b > foldrMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b > > > This has a couple of benefits. On the practical side, we can provide > total alternatives > to existing partial functions (IE: 'foldr1' and friends). It also > enables us to fold > over containers using a semigroup instance, which comes up suprisingly > often. > > Naming: > > -------------------------------------------------------------------------------- > Historically, the biggest source of controversy with this proposal has > been over the > name. The class currently exists in semigroupoids [3] under the name > 'Foldable1', though > there was some discussion around renaming it to 'SemiFoldable' [4]. > However, if we keep > the name unchanged, it makes the migration path nice and > straightforward, and the possible > name conflict with Data.Functor.Classes seems unlikely. > > Migration: > > -------------------------------------------------------------------------------- > If we decide to go with 'Foldable1' as the name, we should be able to > perform this change with > 0 breakage. > > References: > [1] https://mail.haskell.org/pipermail/libraries/2019-November/030059.html > [2] https://gitlab.haskell.org/ghc/ghc/-/issues/13573 > [3] > https://hackage.haskell.org/package/semigroupoids-5.3.4/docs/Data-Semigroup-Foldable.html#t:Foldable1 > [4] https://github.com/ekmett/semigroupoids/issues/26 > _______________________________________________ > 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 reedmullanix at gmail.com Thu Dec 10 07:20:20 2020 From: reedmullanix at gmail.com (Reed Mullanix) Date: Wed, 9 Dec 2020 23:20:20 -0800 Subject: Proposal: Add 'Foldable1' to base In-Reply-To: References: Message-ID: Seems reasonable to me! I definitely agree that we ought to add a strict foldMap1 to the version found in semigroupoids. On Wed, Dec 9, 2020 at 11:08 PM David Feuer wrote: > > That seems rather large to me, and some of those methods don't have much if any historical usage. I'd recommend starting with a slightly smaller class. It's always easier to add more later than to remove. My suggestion: > > foldMap1 :: Semigroup m => (a -> m) -> t a -> m > > foldMap1' :: Semigroup m => (a -> m) -> t a -> m > > toNonEmpty :: t a -> NonEmpty a > > The rest can be exported as functions, rather than methods, to begin with. > > On Thu, Dec 10, 2020, 1:38 AM Reed Mullanix wrote: >> >> With the recent discussion around the addition of 'intersection' to containers, >> I think it might be a good time to re-open the discussion surrounding adding >> 'Foldable1' to base. >> >> For context, 'Foldable1' would be a subclass of 'Foldable' that abstracts >> folds over non-empty containers. Alternatively, it can be seen as a method >> of combining together the elements of a container using a semigroup. >> The contents of this class have been discussed previously (See [1,2]), >> and the version presented in this proposal is taken from [1]. >> >> class Foldable t => Foldable1 t where >> {-# MINIMAL foldMap1 | foldr1map #-} >> >> fold1 :: Semigroup m => t m -> m >> >> -- the defining member, like foldMap but only asking for Semigroup >> foldMap1 :: Semigroup m => (a -> m) -> t a -> m >> >> -- strict foldMap1, cf foldMap' >> foldMap1' :: Semigroup m => (a -> m) -> t a -> m >> >> -- analogue of toList >> toNonEmpty :: t a -> NonEmpty a >> >> -- left&right, strict&non-strict folds >> foldr1 :: (a -> a -> a) -> t a -> a >> foldr1' :: (a -> a -> a) -> t a -> a >> foldl1 :: (a -> a -> a) -> t a -> a >> foldl1' :: (a -> a -> a) -> t a -> a >> >> -- these can have efficient implementation for NonEmptySet >> maximum1 :: Ord a => t a -> a >> minimum1 :: Ord a => t a -> a >> >> -- head1 have efficient implementation for NonEmpty and Tree >> -- last1 for symmetry >> head1 :: t a -> a >> last1 :: t a -> a >> >> -- fold variants with premap. >> -- Without this map, we cannot implement foldl using foldr etc. >> foldrMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b >> foldlMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b >> foldlMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b >> foldrMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b >> >> >> This has a couple of benefits. On the practical side, we can provide >> total alternatives >> to existing partial functions (IE: 'foldr1' and friends). It also >> enables us to fold >> over containers using a semigroup instance, which comes up suprisingly often. >> >> Naming: >> -------------------------------------------------------------------------------- >> Historically, the biggest source of controversy with this proposal has >> been over the >> name. The class currently exists in semigroupoids [3] under the name >> 'Foldable1', though >> there was some discussion around renaming it to 'SemiFoldable' [4]. >> However, if we keep >> the name unchanged, it makes the migration path nice and >> straightforward, and the possible >> name conflict with Data.Functor.Classes seems unlikely. >> >> Migration: >> -------------------------------------------------------------------------------- >> If we decide to go with 'Foldable1' as the name, we should be able to >> perform this change with >> 0 breakage. >> >> References: >> [1] https://mail.haskell.org/pipermail/libraries/2019-November/030059.html >> [2] https://gitlab.haskell.org/ghc/ghc/-/issues/13573 >> [3] https://hackage.haskell.org/package/semigroupoids-5.3.4/docs/Data-Semigroup-Foldable.html#t:Foldable1 >> [4] https://github.com/ekmett/semigroupoids/issues/26 >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From simon.jakobi at googlemail.com Thu Dec 10 11:26:23 2020 From: simon.jakobi at googlemail.com (Simon Jakobi) Date: Thu, 10 Dec 2020 12:26:23 +0100 Subject: Proposal: Add 'Foldable1' to base In-Reply-To: References: Message-ID: +1 Am Do., 10. Dez. 2020 um 08:20 Uhr schrieb Reed Mullanix : > > Seems reasonable to me! I definitely agree that we ought to add a > strict foldMap1 to the version found in semigroupoids. > > On Wed, Dec 9, 2020 at 11:08 PM David Feuer wrote: > > > > That seems rather large to me, and some of those methods don't have much if any historical usage. I'd recommend starting with a slightly smaller class. It's always easier to add more later than to remove. My suggestion: > > > > foldMap1 :: Semigroup m => (a -> m) -> t a -> m > > > > foldMap1' :: Semigroup m => (a -> m) -> t a -> m > > > > toNonEmpty :: t a -> NonEmpty a > > > > The rest can be exported as functions, rather than methods, to begin with. > > > > On Thu, Dec 10, 2020, 1:38 AM Reed Mullanix wrote: > >> > >> With the recent discussion around the addition of 'intersection' to containers, > >> I think it might be a good time to re-open the discussion surrounding adding > >> 'Foldable1' to base. > >> > >> For context, 'Foldable1' would be a subclass of 'Foldable' that abstracts > >> folds over non-empty containers. Alternatively, it can be seen as a method > >> of combining together the elements of a container using a semigroup. > >> The contents of this class have been discussed previously (See [1,2]), > >> and the version presented in this proposal is taken from [1]. > >> > >> class Foldable t => Foldable1 t where > >> {-# MINIMAL foldMap1 | foldr1map #-} > >> > >> fold1 :: Semigroup m => t m -> m > >> > >> -- the defining member, like foldMap but only asking for Semigroup > >> foldMap1 :: Semigroup m => (a -> m) -> t a -> m > >> > >> -- strict foldMap1, cf foldMap' > >> foldMap1' :: Semigroup m => (a -> m) -> t a -> m > >> > >> -- analogue of toList > >> toNonEmpty :: t a -> NonEmpty a > >> > >> -- left&right, strict&non-strict folds > >> foldr1 :: (a -> a -> a) -> t a -> a > >> foldr1' :: (a -> a -> a) -> t a -> a > >> foldl1 :: (a -> a -> a) -> t a -> a > >> foldl1' :: (a -> a -> a) -> t a -> a > >> > >> -- these can have efficient implementation for NonEmptySet > >> maximum1 :: Ord a => t a -> a > >> minimum1 :: Ord a => t a -> a > >> > >> -- head1 have efficient implementation for NonEmpty and Tree > >> -- last1 for symmetry > >> head1 :: t a -> a > >> last1 :: t a -> a > >> > >> -- fold variants with premap. > >> -- Without this map, we cannot implement foldl using foldr etc. > >> foldrMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b > >> foldlMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b > >> foldlMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b > >> foldrMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b > >> > >> > >> This has a couple of benefits. On the practical side, we can provide > >> total alternatives > >> to existing partial functions (IE: 'foldr1' and friends). It also > >> enables us to fold > >> over containers using a semigroup instance, which comes up suprisingly often. > >> > >> Naming: > >> -------------------------------------------------------------------------------- > >> Historically, the biggest source of controversy with this proposal has > >> been over the > >> name. The class currently exists in semigroupoids [3] under the name > >> 'Foldable1', though > >> there was some discussion around renaming it to 'SemiFoldable' [4]. > >> However, if we keep > >> the name unchanged, it makes the migration path nice and > >> straightforward, and the possible > >> name conflict with Data.Functor.Classes seems unlikely. > >> > >> Migration: > >> -------------------------------------------------------------------------------- > >> If we decide to go with 'Foldable1' as the name, we should be able to > >> perform this change with > >> 0 breakage. > >> > >> References: > >> [1] https://mail.haskell.org/pipermail/libraries/2019-November/030059.html > >> [2] https://gitlab.haskell.org/ghc/ghc/-/issues/13573 > >> [3] https://hackage.haskell.org/package/semigroupoids-5.3.4/docs/Data-Semigroup-Foldable.html#t:Foldable1 > >> [4] https://github.com/ekmett/semigroupoids/issues/26 > >> _______________________________________________ > >> 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 godzbanebane at gmail.com Thu Dec 10 12:09:35 2020 From: godzbanebane at gmail.com (Georgi Lyubenov) Date: Thu, 10 Dec 2020 14:09:35 +0200 Subject: Proposal: Add 'Foldable1' to base In-Reply-To: References: Message-ID: +1 -------------- next part -------------- An HTML attachment was scrubbed... URL: From tonymorris at gmail.com Fri Dec 11 12:36:27 2020 From: tonymorris at gmail.com (Tony Morris) Date: Fri, 11 Dec 2020 22:36:27 +1000 Subject: Proposal: Add 'Foldable1' to base In-Reply-To: References: Message-ID: <54e2ee88-fb33-67cb-f51b-05be8b6e03e4@gmail.com> Delete head1 and last1 and you'll get my +1. (they are better written as optics, when we also get Apply into base) On 12/10/20 4:37 PM, Reed Mullanix wrote: > With the recent discussion around the addition of 'intersection' to containers, > I think it might be a good time to re-open the discussion surrounding adding > 'Foldable1' to base. > > For context, 'Foldable1' would be a subclass of 'Foldable' that abstracts > folds over non-empty containers. Alternatively, it can be seen as a method > of combining together the elements of a container using a semigroup. > The contents of this class have been discussed previously (See [1,2]), > and the version presented in this proposal is taken from [1]. > > class Foldable t => Foldable1 t where > {-# MINIMAL foldMap1 | foldr1map #-} > > fold1 :: Semigroup m => t m -> m > > -- the defining member, like foldMap but only asking for Semigroup > foldMap1 :: Semigroup m => (a -> m) -> t a -> m > > -- strict foldMap1, cf foldMap' > foldMap1' :: Semigroup m => (a -> m) -> t a -> m > > -- analogue of toList > toNonEmpty :: t a -> NonEmpty a > > -- left&right, strict&non-strict folds > foldr1 :: (a -> a -> a) -> t a -> a > foldr1' :: (a -> a -> a) -> t a -> a > foldl1 :: (a -> a -> a) -> t a -> a > foldl1' :: (a -> a -> a) -> t a -> a > > -- these can have efficient implementation for NonEmptySet > maximum1 :: Ord a => t a -> a > minimum1 :: Ord a => t a -> a > > -- head1 have efficient implementation for NonEmpty and Tree > -- last1 for symmetry > head1 :: t a -> a > last1 :: t a -> a > > -- fold variants with premap. > -- Without this map, we cannot implement foldl using foldr etc. > foldrMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b > foldlMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b > foldlMap1 :: (a -> b) -> (b -> b -> b) -> t a -> b > foldrMap1' :: (a -> b) -> (b -> b -> b) -> t a -> b > > > This has a couple of benefits. On the practical side, we can provide > total alternatives > to existing partial functions (IE: 'foldr1' and friends). It also > enables us to fold > over containers using a semigroup instance, which comes up suprisingly often. > > Naming: > -------------------------------------------------------------------------------- > Historically, the biggest source of controversy with this proposal has > been over the > name. The class currently exists in semigroupoids [3] under the name > 'Foldable1', though > there was some discussion around renaming it to 'SemiFoldable' [4]. > However, if we keep > the name unchanged, it makes the migration path nice and > straightforward, and the possible > name conflict with Data.Functor.Classes seems unlikely. > > Migration: > -------------------------------------------------------------------------------- > If we decide to go with 'Foldable1' as the name, we should be able to > perform this change with > 0 breakage. > > References: > [1] https://mail.haskell.org/pipermail/libraries/2019-November/030059.html > [2] https://gitlab.haskell.org/ghc/ghc/-/issues/13573 > [3] https://hackage.haskell.org/package/semigroupoids-5.3.4/docs/Data-Semigroup-Foldable.html#t:Foldable1 > [4] https://github.com/ekmett/semigroupoids/issues/26 > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From ben.franksen at online.de Sun Dec 20 22:05:39 2020 From: ben.franksen at online.de (Ben Franksen) Date: Sun, 20 Dec 2020 23:05:39 +0100 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: Am 06.12.20 um 19:58 schrieb Sven Panne: > To me it's just the other way around: It violates aesthetics if it doesn't > follow the mathematical definition in all cases, which is why I don't like > NonEmpty here. I think you've got that wrong. x `elem` intersections [] = {definition} forall xs in []. x `elem` xs = {vacuous forall} true Any proposition P(x) is true for all x in []. So the mathematical definition of intersections::[Set a]-> Set a would not be the empty set but the set of all x:a, which in general we have no way to construct. Cheers Ben From ietf-dane at dukhovni.org Sun Dec 20 22:15:57 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 20 Dec 2020 17:15:57 -0500 Subject: Adding partial foldl1' to Foldable? Message-ID: Given that Foldable currently has: - foldr and foldr' - foldl and foldl' - foldMap and foldMap' and also has only: - foldr1 - foldl1 it seems natural to ask whether there it should also have a strict variant of at least foldl1, since the non-strict variant has rather limited applicability, and users would/should in most cases want/use the strict `foldl1'` instead. -- Viktor. P.S. I just joined the list today, but noticed that coincidentally, there's already a recent dicussion of Foldable1, which rather overlaps with this question, and perhaps the partial `foldr1` and `foldl1` should be seen as deprecated, once a suitable class of non-empty containers provides total variants. But perhaps on the other hand, given that the partial functions already exist, perhaps adding the strict companions is warranted? I am asking because I am writing some expository prose for Data.Foldable, to go at the bottom of the document, structurally along the lines of what I contributed for Data.Traversable, but with a fairly different focus. The goal is draw careful distinctions between strict recursive and lazy corecursive reductions, explaining their proper usage and typical implementations. The "missing" `foldl1'` was something I ran into while working on part of the writeup. From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Mon Dec 21 10:12:37 2020 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Mon, 21 Dec 2020 10:12:37 +0000 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: Message-ID: <20201221101237.GD28742@cloudinit-builder> On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: > Am 06.12.20 um 19:58 schrieb Sven Panne: > > To me it's just the other way around: It violates aesthetics if it doesn't > > follow the mathematical definition in all cases, which is why I don't like > > NonEmpty here. > > I think you've got that wrong. > > x `elem` intersections [] > = {definition} > forall xs in []. x `elem` xs > = {vacuous forall} > true > > Any proposition P(x) is true for all x in []. So the mathematical > definition of intersections::[Set a]-> Set a would not be the empty set > but the set of all x:a, which in general we have no way to construct. Yes, and to bring this back to Sven's original claim | Why NonEmpty? I would expect "intersections [] = Set.empty", because | the result contains all the elements which are in all sets, | i.e. none. That's at least my intuition, is there some law which | this would violate? the correct definition of "intersections []" should be "all elements which are in all of no sets" i.e. _every_ value of the given type! Tom From david.feuer at gmail.com Mon Dec 21 15:56:49 2020 From: david.feuer at gmail.com (David Feuer) Date: Mon, 21 Dec 2020 10:56:49 -0500 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: <20201221101237.GD28742@cloudinit-builder> References: <20201221101237.GD28742@cloudinit-builder> Message-ID: One *could* write import Data.Universe.Class (Finite (..)) class (Ord a, Finite a) => OrderedFinite a where orderedFiniteUniverse :: Set a orderedFiniteUniverse = S.fromList universeF data SMaybe a = SJust !a | SNothing wackyIntersections :: OrderedFinite a => [Set a] -> Set a wackyIntersections = \ss -> foldr go stop ss SNothing where stop SNothing = orderedFiniteUniverse stop (SJust s) = s go s r SNothing = r (SJust s) go s r (SJust acc) | null acc = empty | otherwise = r (SJust acc `intersection` s) No such things will be going in `containers`, but perhaps they would fit in `universe`. On Mon, Dec 21, 2020 at 5:12 AM Tom Ellis wrote: > > On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: > > Am 06.12.20 um 19:58 schrieb Sven Panne: > > > To me it's just the other way around: It violates aesthetics if it doesn't > > > follow the mathematical definition in all cases, which is why I don't like > > > NonEmpty here. > > > > I think you've got that wrong. > > > > x `elem` intersections [] > > = {definition} > > forall xs in []. x `elem` xs > > = {vacuous forall} > > true > > > > Any proposition P(x) is true for all x in []. So the mathematical > > definition of intersections::[Set a]-> Set a would not be the empty set > > but the set of all x:a, which in general we have no way to construct. > > Yes, and to bring this back to Sven's original claim > > | Why NonEmpty? I would expect "intersections [] = Set.empty", because > | the result contains all the elements which are in all sets, > | i.e. none. That's at least my intuition, is there some law which > | this would violate? > > the correct definition of "intersections []" should be "all elements > which are in all of no sets" i.e. _every_ value of the given type! > > Tom > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From carter.schonwald at gmail.com Mon Dec 21 16:12:27 2020 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Mon, 21 Dec 2020 11:12:27 -0500 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: <20201221101237.GD28742@cloudinit-builder> References: <20201221101237.GD28742@cloudinit-builder> Message-ID: why are we equating the lattice operators for True and false with the lattice operators for set? (for both structures, we have the dual partial order is also a lattice, so unless we have ) (i'm going to get the names of these equations wrong, but ) the "identity" law is going to be max `intersect` y == y , min `union` y === y the "absorbing" law is going to be min `intersect` y == min , max `union` y == max these rules work the same for (min = emptyset, max == full set, union == set union, intersect == set intersecct) OR for its dual lattice (min == full set, max == emtpy set, union = set intersection, intersect == set union) at some level arguing about the empty list case turns into artifacts of "simple" definitions that said, i suppose a case could be made that for intersect :: [a] -> a , that as the list argument gets larger the result should be getting *smaller*, so list intersect of lattice elements should be "anti-monotone", and list union should be monotone (the result gets bigger). I dont usually see tht either way, I do strongly feel that either way, arguing by how we choose to relate the boolean lattice and seet lattices is perhaps the wrong choice... because both lattices are equivalent to theeir dual lattice On Mon, Dec 21, 2020 at 5:12 AM Tom Ellis < tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: > On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: > > Am 06.12.20 um 19:58 schrieb Sven Panne: > > > To me it's just the other way around: It violates aesthetics if it > doesn't > > > follow the mathematical definition in all cases, which is why I don't > like > > > NonEmpty here. > > > > I think you've got that wrong. > > > > x `elem` intersections [] > > = {definition} > > forall xs in []. x `elem` xs > > = {vacuous forall} > > true > > > > Any proposition P(x) is true for all x in []. So the mathematical > > definition of intersections::[Set a]-> Set a would not be the empty set > > but the set of all x:a, which in general we have no way to construct. > > Yes, and to bring this back to Sven's original claim > > | Why NonEmpty? I would expect "intersections [] = Set.empty", because > | the result contains all the elements which are in all sets, > | i.e. none. That's at least my intuition, is there some law which > | this would violate? > > the correct definition of "intersections []" should be "all elements > which are in all of no sets" i.e. _every_ value of the given type! > > Tom > _______________________________________________ > 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 carter.schonwald at gmail.com Mon Dec 21 16:14:14 2020 From: carter.schonwald at gmail.com (Carter Schonwald) Date: Mon, 21 Dec 2020 11:14:14 -0500 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: edit: neglected to mention that choosing which lattice (and or dual) to use only really matters when considering products/sums of lattices to form new lattices On Mon, Dec 21, 2020 at 11:12 AM Carter Schonwald < carter.schonwald at gmail.com> wrote: > why are we equating the lattice operators for True and false with the > lattice operators for set? (for both structures, we have the dual partial > order is also a lattice, so unless we have ) > (i'm going to get the names of these equations wrong, but ) > > the "identity" law is going to be max `intersect` y == y , min `union` y > === y > > the "absorbing" law is going to be min `intersect` y == min , max > `union` y == max > > these rules work the same for (min = emptyset, max == full set, union == > set union, intersect == set intersecct) > OR for its dual lattice (min == full set, max == emtpy set, union = set > intersection, intersect == set union) > > at some level arguing about the empty list case turns into artifacts of > "simple" definitions > > that said, i suppose a case could be made that for intersect :: [a] -> a , > that as the list argument gets larger the result should be getting > *smaller*, so list intersect of lattice elements should be "anti-monotone", > and list union should be monotone (the result gets bigger). I dont usually > see tht > > either way, I do strongly feel that either way, arguing by how we choose > to relate the boolean lattice and seet lattices is perhaps the wrong > choice... because both lattices are equivalent to theeir dual lattice > > On Mon, Dec 21, 2020 at 5:12 AM Tom Ellis < > tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: > >> On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: >> > Am 06.12.20 um 19:58 schrieb Sven Panne: >> > > To me it's just the other way around: It violates aesthetics if it >> doesn't >> > > follow the mathematical definition in all cases, which is why I don't >> like >> > > NonEmpty here. >> > >> > I think you've got that wrong. >> > >> > x `elem` intersections [] >> > = {definition} >> > forall xs in []. x `elem` xs >> > = {vacuous forall} >> > true >> > >> > Any proposition P(x) is true for all x in []. So the mathematical >> > definition of intersections::[Set a]-> Set a would not be the empty set >> > but the set of all x:a, which in general we have no way to construct. >> >> Yes, and to bring this back to Sven's original claim >> >> | Why NonEmpty? I would expect "intersections [] = Set.empty", because >> | the result contains all the elements which are in all sets, >> | i.e. none. That's at least my intuition, is there some law which >> | this would violate? >> >> the correct definition of "intersections []" should be "all elements >> which are in all of no sets" i.e. _every_ value of the given type! >> >> Tom >> _______________________________________________ >> 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 ben.franksen at online.de Mon Dec 21 18:19:49 2020 From: ben.franksen at online.de (Ben Franksen) Date: Mon, 21 Dec 2020 19:19:49 +0100 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: All this talk about lattices reminds me of one of my pet gripes I have with the standard libraries (base), namely that the boolean operators aren't overloaded. I don't want to open endless discussions about the perfect generalization, because there are lots of valid generalizations and the lattice package is fine for those. But most generalizations don't have a 'not' (complement) operator. So, a simple type class Boolean with instances for Bool and functions returning Booleans should cover the majority of use cases; more instances could be added of course. Something like {-# LANGUAGE NoImplicitPrelude #-} module Data.Boolean where import Prelude hiding ((&&),(||),not) import qualified Prelude infixr 3 && infixr 2 || class Boolean a where -- laws: that of a boolean algebra, i.e. -- complemented distributive lattice, see -- https://en.wikipedia.org/wiki/Boolean_algebra#Laws (&&) :: a -> a -> a (||) :: a -> a -> a not :: a -> a top :: a bottom :: a instance Boolean Bool where (&&) = (Prelude.&&) (||) = (Prelude.||) not = Prelude.not top = True bottom = False instance Boolean b => Boolean (a->b) where (f && g) x = f x && g x (f || g) x = f x || g x (not f) x = not (f x) top = const top bottom = const bottom IMHO this would be absolutely benign, no problems with type inference, fully Haskell98, no breakage of existing code I can think of. (I didn't check that last point but I would be very surprised if there were.) Cheers Ben Am 21.12.20 um 17:14 schrieb Carter Schonwald: > edit: neglected to mention that choosing which lattice (and or dual) to use > only really matters when considering products/sums of lattices to form new > lattices > > On Mon, Dec 21, 2020 at 11:12 AM Carter Schonwald < > carter.schonwald at gmail.com> wrote: > >> why are we equating the lattice operators for True and false with the >> lattice operators for set? (for both structures, we have the dual partial >> order is also a lattice, so unless we have ) >> (i'm going to get the names of these equations wrong, but ) >> >> the "identity" law is going to be max `intersect` y == y , min `union` y >> === y >> >> the "absorbing" law is going to be min `intersect` y == min , max >> `union` y == max >> >> these rules work the same for (min = emptyset, max == full set, union == >> set union, intersect == set intersecct) >> OR for its dual lattice (min == full set, max == emtpy set, union = set >> intersection, intersect == set union) >> >> at some level arguing about the empty list case turns into artifacts of >> "simple" definitions >> >> that said, i suppose a case could be made that for intersect :: [a] -> a , >> that as the list argument gets larger the result should be getting >> *smaller*, so list intersect of lattice elements should be "anti-monotone", >> and list union should be monotone (the result gets bigger). I dont usually >> see tht >> >> either way, I do strongly feel that either way, arguing by how we choose >> to relate the boolean lattice and seet lattices is perhaps the wrong >> choice... because both lattices are equivalent to theeir dual lattice >> >> On Mon, Dec 21, 2020 at 5:12 AM Tom Ellis < >> tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: >> >>> On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: >>>> Am 06.12.20 um 19:58 schrieb Sven Panne: >>>>> To me it's just the other way around: It violates aesthetics if it >>> doesn't >>>>> follow the mathematical definition in all cases, which is why I don't >>> like >>>>> NonEmpty here. >>>> >>>> I think you've got that wrong. >>>> >>>> x `elem` intersections [] >>>> = {definition} >>>> forall xs in []. x `elem` xs >>>> = {vacuous forall} >>>> true >>>> >>>> Any proposition P(x) is true for all x in []. So the mathematical >>>> definition of intersections::[Set a]-> Set a would not be the empty set >>>> but the set of all x:a, which in general we have no way to construct. >>> >>> Yes, and to bring this back to Sven's original claim >>> >>> | Why NonEmpty? I would expect "intersections [] = Set.empty", because >>> | the result contains all the elements which are in all sets, >>> | i.e. none. That's at least my intuition, is there some law which >>> | this would violate? >>> >>> the correct definition of "intersections []" should be "all elements >>> which are in all of no sets" i.e. _every_ value of the given type! >>> >>> Tom >>> _______________________________________________ >>> 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 tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Mon Dec 21 18:54:40 2020 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Mon, 21 Dec 2020 18:54:40 +0000 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: <20201221185440.GE28742@cloudinit-builder> On Mon, Dec 21, 2020 at 07:19:49PM +0100, Ben Franksen wrote: > So, a simple type class Boolean with instances for Bool and > functions returning Booleans should cover the majority of use cases; > more instances could be added of course. Something like [...] > instance Boolean Bool where > (&&) = (Prelude.&&) > (||) = (Prelude.||) > not = Prelude.not > top = True > bottom = False > > instance Boolean b => Boolean (a->b) where > (f && g) x = f x && g x > (f || g) x = f x || g x > (not f) x = not (f x) > top = const top > bottom = const bottom I think it's worth seeing more instances. As it is I don't understand in what situations one would use these polymorphically and therefore why `liftA2 (&&)`, `fmap not`, `pure True` and friends wouldn't suffice. Tom From oleg.grenrus at iki.fi Mon Dec 21 20:04:35 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Mon, 21 Dec 2020 22:04:35 +0200 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: <1a647df1-f153-5e84-7b11-a74e6360bc14@iki.fi> lattice package has 'not': https://hackage.haskell.org/package/lattices-2.0.2/docs/Algebra-Heyting.html#v:neg - Oleg On 21.12.2020 20.19, Ben Franksen wrote: > All this talk about lattices reminds me of one of my pet gripes I have > with the standard libraries (base), namely that the boolean operators > aren't overloaded. I don't want to open endless discussions about the > perfect generalization, because there are lots of valid generalizations > and the lattice package is fine for those. > > But most generalizations don't have a 'not' (complement) operator. So, a > simple type class Boolean with instances for Bool and functions > returning Booleans should cover the majority of use cases; more > instances could be added of course. Something like > > {-# LANGUAGE NoImplicitPrelude #-} > module Data.Boolean where > > import Prelude hiding ((&&),(||),not) > import qualified Prelude > > infixr 3 && > infixr 2 || > > class Boolean a where > -- laws: that of a boolean algebra, i.e. > -- complemented distributive lattice, see > -- https://en.wikipedia.org/wiki/Boolean_algebra#Laws > (&&) :: a -> a -> a > (||) :: a -> a -> a > not :: a -> a > top :: a > bottom :: a > > instance Boolean Bool where > (&&) = (Prelude.&&) > (||) = (Prelude.||) > not = Prelude.not > top = True > bottom = False > > instance Boolean b => Boolean (a->b) where > (f && g) x = f x && g x > (f || g) x = f x || g x > (not f) x = not (f x) > top = const top > bottom = const bottom > > IMHO this would be absolutely benign, no problems with type inference, > fully Haskell98, no breakage of existing code I can think of. (I didn't > check that last point but I would be very surprised if there were.) > > Cheers > Ben > > Am 21.12.20 um 17:14 schrieb Carter Schonwald: >> edit: neglected to mention that choosing which lattice (and or dual) to use >> only really matters when considering products/sums of lattices to form new >> lattices >> >> On Mon, Dec 21, 2020 at 11:12 AM Carter Schonwald < >> carter.schonwald at gmail.com> wrote: >> >>> why are we equating the lattice operators for True and false with the >>> lattice operators for set? (for both structures, we have the dual partial >>> order is also a lattice, so unless we have ) >>> (i'm going to get the names of these equations wrong, but ) >>> >>> the "identity" law is going to be max `intersect` y == y , min `union` y >>> === y >>> >>> the "absorbing" law is going to be min `intersect` y == min , max >>> `union` y == max >>> >>> these rules work the same for (min = emptyset, max == full set, union == >>> set union, intersect == set intersecct) >>> OR for its dual lattice (min == full set, max == emtpy set, union = set >>> intersection, intersect == set union) >>> >>> at some level arguing about the empty list case turns into artifacts of >>> "simple" definitions >>> >>> that said, i suppose a case could be made that for intersect :: [a] -> a , >>> that as the list argument gets larger the result should be getting >>> *smaller*, so list intersect of lattice elements should be "anti-monotone", >>> and list union should be monotone (the result gets bigger). I dont usually >>> see tht >>> >>> either way, I do strongly feel that either way, arguing by how we choose >>> to relate the boolean lattice and seet lattices is perhaps the wrong >>> choice... because both lattices are equivalent to theeir dual lattice >>> >>> On Mon, Dec 21, 2020 at 5:12 AM Tom Ellis < >>> tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: >>> >>>> On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: >>>>> Am 06.12.20 um 19:58 schrieb Sven Panne: >>>>>> To me it's just the other way around: It violates aesthetics if it >>>> doesn't >>>>>> follow the mathematical definition in all cases, which is why I don't >>>> like >>>>>> NonEmpty here. >>>>> I think you've got that wrong. >>>>> >>>>> x `elem` intersections [] >>>>> = {definition} >>>>> forall xs in []. x `elem` xs >>>>> = {vacuous forall} >>>>> true >>>>> >>>>> Any proposition P(x) is true for all x in []. So the mathematical >>>>> definition of intersections::[Set a]-> Set a would not be the empty set >>>>> but the set of all x:a, which in general we have no way to construct. >>>> Yes, and to bring this back to Sven's original claim >>>> >>>> | Why NonEmpty? I would expect "intersections [] = Set.empty", because >>>> | the result contains all the elements which are in all sets, >>>> | i.e. none. That's at least my intuition, is there some law which >>>> | this would violate? >>>> >>>> the correct definition of "intersections []" should be "all elements >>>> which are in all of no sets" i.e. _every_ value of the given type! >>>> >>>> Tom >>>> _______________________________________________ >>>> 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 From casper at unbc.ca Mon Dec 21 22:06:33 2020 From: casper at unbc.ca (David Casperson) Date: Mon, 21 Dec 2020 14:06:33 -0800 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: Hi Carter, not sure if I understand exactly what you are getting at here, but there IS a strong connection, via membership, between lattices on True/False and set lattices: x ∈ A ∪ B iff x ∈ A ∨ x ∈ B x ∈ A ∩ B iff x ∈ A ∧ x ∈ B x ∈ A' iff ¬ (x ∈ A) and, in particular, x ∈ ∩(A ∈ P) iff ∀(A∈P) [x ∈ A] Lattices aren't necessarily isomorphic to their duals, even with bounded lattices. (Take, for instance, lcm and gcd on the non-negative integers. The primes are atoms, there are no co-atoms. [1]) WITH COMPLEMENT, sets form a boolean algebra which is self-dual via De Morgan's lawas, but you need to have a universe against which to compute complements. Without complementation there isn't necessarily duality. Take for instance, finite subsets of the integers. Am I missing your point? cheers, David -- David Casperson, PhD, R.P., | David.Casperson at unbc.ca Associate Professor and Chair, | (250) 960-6672 Fax 960-5544 Computer Science | 3333 University Way University of Northern British Columbia | Prince George, BC V2N 4Z9 | CANADA [1] several decades ago it took me an embarrasingly long time to convince the Maple community that lcm(0,0)=0 was the sensible lattice-theoretic definition. Carter Schonwald, on 2020-12-21, you wrote: > From: Carter Schonwald > To: Tom Ellis , > Haskell Libraries > Date: Mon, 21 Dec 2020 08:12:27 > Subject: Re: containers: intersections for Set, along with Semigroup newtype > Message-ID: > > > > CAUTION: This email is not from UNBC. Avoid links and attachments. Don't buy gift cards. > > why are we equating the lattice operators for True and false with the lattice operators for set? (for both > structures, we have the dual partial order is also a lattice, so unless we have ) > (i'm going to get the names of these equations wrong, but ) > > the "identity" law is going to be  max `intersect` y == y ,  min `union` y === y > > the "absorbing" law is going to be   min `intersect` y == min , max `union` y == max > > these rules work the same for (min = emptyset, max == full set, union == set union, intersect == set intersecct) > OR for its dual lattice (min == full set, max == emtpy set, union = set intersection, intersect == set union) > > at some level arguing about the empty list case turns into artifacts of "simple" definitions > > that said, i suppose a case could be made that for intersect :: [a] -> a , that as the list argument gets larger the > result should be getting *smaller*, so list intersect of lattice elements should be "anti-monotone", and list union > should be monotone (the result gets bigger). I dont usually see tht > > either way, I do strongly feel that either way, arguing by how we choose to relate the boolean lattice and seet > lattices is perhaps the wrong choice... because both lattices are equivalent to theeir dual lattice > > On Mon, Dec 21, 2020 at 5:12 AM Tom Ellis wrote: > On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: > > Am 06.12.20 um 19:58 schrieb Sven Panne: > > > To me it's just the other way around: It violates aesthetics if it doesn't > > > follow the mathematical definition in all cases, which is why I don't like > > > NonEmpty here. > > > > I think you've got that wrong. > > > >   x `elem` intersections [] > > = {definition} > >   forall xs in []. x `elem` xs > > = {vacuous forall} > >   true > > > > Any proposition P(x) is true for all x in []. So the mathematical > > definition of intersections::[Set a]-> Set a would not be the empty set > > but the set of all x:a, which in general we have no way to construct. > > Yes, and to bring this back to Sven's original claim > > | Why NonEmpty? I would expect "intersections [] = Set.empty", because > | the result contains all the elements which are in all sets, > | i.e. none. That's at least my intuition, is there some law which > | this would violate? > > the correct definition of "intersections []" should be "all elements > which are in all of no sets" i.e. _every_ value of the given type! > > Tom > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > -------------- next part -------------- _______________________________________________ Libraries mailing list Libraries at haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From ietf-dane at dukhovni.org Mon Dec 21 22:25:40 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Mon, 21 Dec 2020 17:25:40 -0500 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: On Mon, Dec 21, 2020 at 02:06:33PM -0800, David Casperson wrote: > Lattices aren't necessarily isomorphic to their duals, even with > bounded lattices. (Take, for instance, lcm and gcd on the > non-negative integers. The primes are atoms, there are no > co-atoms. [1]) But the non-negative integers with gcd and lcm are surely not a bounded lattice. If we introduce an upper bound by restricting attention to numbers that are factors of some number n > 1, then surely co-atoms reappear in the form of n/p for each prime factor of n. -- Viktor. From ben.franksen at online.de Mon Dec 21 23:21:04 2020 From: ben.franksen at online.de (Ben Franksen) Date: Tue, 22 Dec 2020 00:21:04 +0100 Subject: type class Boolean In-Reply-To: <20201221185440.GE28742@cloudinit-builder> References: <20201221101237.GD28742@cloudinit-builder> <20201221185440.GE28742@cloudinit-builder> Message-ID: Am 21.12.20 um 19:54 schrieb Tom Ellis: > I think it's worth seeing more instances. As it is I don't understand > in what situations one would use these polymorphically and therefore > why `liftA2 (&&)`, `fmap not`, `pure True` and friends wouldn't > suffice. As with all overloading it's partly a matter of convenience. For instance you can't use 'liftA2 (&&)' as an operator. And your list of alternatives above demonstrates that one has to remember which lifting operator (pure, fmap, liftA2) to use, depending on arity. From casper at unbc.ca Mon Dec 21 23:25:19 2020 From: casper at unbc.ca (David Casperson) Date: Mon, 21 Dec 2020 15:25:19 -0800 Subject: containers: intersections for Set, along with Semigroup newtype In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: Hi Viktor. On 2020-12-21, you wrote: > From: Viktor Dukhovni > To: libraries at haskell.org > Reply-To: libraries at haskell.org > Date: Mon, 21 Dec 2020 14:25:40 > Subject: Re: containers: intersections for Set, along with Semigroup newtype > Message-ID: > > On Mon, Dec 21, 2020 at 02:06:33PM -0800, David Casperson wrote: > >> Lattices aren't necessarily isomorphic to their duals, even with >> bounded lattices. (Take, for instance, lcm and gcd on the >> non-negative integers. The primes are atoms, there are no >> co-atoms. [1]) > > But the non-negative integers with gcd and lcm are surely not a bounded > lattice. If we introduce an upper bound by restricting attention to > numbers that are factors of some number n > 1, then surely co-atoms > reappear in the form of n/p for each prime factor of n. If we define a partial order by x≤y iff x divides y (x|y in the sequel, meaning for clarity ∃k kx=y) there is a lattice structure giving by meet being gcd, and join by lcm, and there are bounds: ∀x 1|x, and ∀x x|0, so 1 is ⊥, and 0 is ⊤. Regardless of whether one likes having 0|0, this is a perfectly well-defined lattice, and there are no co-atoms; there is no largest (w.r.t. |) non-negative integer not divisible by 3. Some people want to insist that x|y ifF y/x exists, that is, ∃!k kx=y, in which case all of the preceding paragraph is true, except for the fact that we no longer have a lattice because we are refusing to define 0∨0 and 0∧0, notwithstanding the existence of a consistent possible extension. Alternatively, take your favourite lower-bounded, upper-unbounded lattice, and add an element ∞, and extend meet and join so that x∧∞=x, x∨∞=∞. You can check that the result also satisfies the lattice laws. Happy Solstice! stay safe! David -- David Casperson Computer Science From ben.franksen at online.de Mon Dec 21 23:28:06 2020 From: ben.franksen at online.de (Ben Franksen) Date: Tue, 22 Dec 2020 00:28:06 +0100 Subject: type class Boolean In-Reply-To: <1a647df1-f153-5e84-7b11-a74e6360bc14@iki.fi> References: <20201221101237.GD28742@cloudinit-builder> <1a647df1-f153-5e84-7b11-a74e6360bc14@iki.fi> Message-ID: Am 21.12.20 um 21:04 schrieb Oleg Grenrus: > lattice package has 'not': > https://hackage.haskell.org/package/lattices-2.0.2/docs/Algebra-Heyting.html#v:neg Oh, nice! (Though 'neg' is not quite as suggestive as 'not'.) From ollie at ocharles.org.uk Mon Dec 21 23:27:43 2020 From: ollie at ocharles.org.uk (Oliver Charles) Date: Mon, 21 Dec 2020 23:27:43 +0000 Subject: type class Boolean In-Reply-To: <20201221185440.GE28742@cloudinit-builder> References: <20201221101237.GD28742@cloudinit-builder> <20201221185440.GE28742@cloudinit-builder> Message-ID: <3afdf05a-0559-4099-9cae-8d6c05e5891c@www.fastmail.com> I've wanted it when writing DSLs. For example, when doing SQL query generation, if you have some Expr a type to represent database expressions of type 'a', it'd be nice to be able to have && "just work" on them, much like how we can add a Num (Expr a) instance. If other functions were written in terms of Bool, these are trivially useful on Expr now, but without that they have to be re-implemented. On Mon, 21 Dec 2020, at 6:54 PM, Tom Ellis wrote: > On Mon, Dec 21, 2020 at 07:19:49PM +0100, Ben Franksen wrote: > > So, a simple type class Boolean with instances for Bool and > > functions returning Booleans should cover the majority of use cases; > > more instances could be added of course. Something like > [...] > > instance Boolean Bool where > > (&&) = (Prelude.&&) > > (||) = (Prelude.||) > > not = Prelude.not > > top = True > > bottom = False > > > > instance Boolean b => Boolean (a->b) where > > (f && g) x = f x && g x > > (f || g) x = f x || g x > > (not f) x = not (f x) > > top = const top > > bottom = const bottom > > I think it's worth seeing more instances. As it is I don't understand > in what situations one would use these polymorphically and therefore > why `liftA2 (&&)`, `fmap not`, `pure True` and friends wouldn't > suffice. > > Tom > _______________________________________________ > 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 tikhon at jelv.is Mon Dec 21 23:32:26 2020 From: tikhon at jelv.is (Tikhon Jelvis) Date: Mon, 21 Dec 2020 15:32:26 -0800 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> <20201221185440.GE28742@cloudinit-builder> Message-ID: For me, the most useful kind of instance would be symbolic booleans like SBV's SBool type. A real bonus would be making if-then-else polymorphic as well—although that doesn't really fit with the lattice abstraction. I know we can do that with RebindableSyntax, but that is a *heavyweight* extension to enable! Breaking boolean behavior up into a few different classes would work for this application. Boolean algebras for and/not/etc, Conditional for ifThenElse and maybe even Boolish or something for True and False pattern synonyms (or just true and false constants). I don't think all of this belongs in base, but making booleans and boolean operators more polymorphic would definitely be useful. On Mon, Dec 21, 2020 at 3:21 PM Ben Franksen wrote: > Am 21.12.20 um 19:54 schrieb Tom Ellis: > > I think it's worth seeing more instances. As it is I don't understand > > in what situations one would use these polymorphically and therefore > > why `liftA2 (&&)`, `fmap not`, `pure True` and friends wouldn't > > suffice. > > As with all overloading it's partly a matter of convenience. For > instance you can't use 'liftA2 (&&)' as an operator. And your list of > alternatives above demonstrates that one has to remember which lifting > operator (pure, fmap, liftA2) to use, depending on arity. > > _______________________________________________ > 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 Mon Dec 21 23:49:18 2020 From: david.feuer at gmail.com (David Feuer) Date: Mon, 21 Dec 2020 18:49:18 -0500 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> <20201221185440.GE28742@cloudinit-builder> Message-ID: I imagine you'd want (&&) and (||) to live in a Lattice class, `bottom` and `top` in `BoundedBelow` and `BoundedAbove`, respectively, and `not` in a `Boolean` one. The relationship between Lattice, JoinSemilattice, and MeetSemilattice is unfortunately awkward (much like that between Ring, AbelianGroup, and Monoid), but mumble mumble something. On Mon, Dec 21, 2020 at 6:32 PM Tikhon Jelvis wrote: > > For me, the most useful kind of instance would be symbolic booleans like SBV's SBool type. > > A real bonus would be making if-then-else polymorphic as well—although that doesn't really fit with the lattice abstraction. I know we can do that with RebindableSyntax, but that is a *heavyweight* extension to enable! > > Breaking boolean behavior up into a few different classes would work for this application. Boolean algebras for and/not/etc, Conditional for ifThenElse and maybe even Boolish or something for True and False pattern synonyms (or just true and false constants). > > I don't think all of this belongs in base, but making booleans and boolean operators more polymorphic would definitely be useful. > > On Mon, Dec 21, 2020 at 3:21 PM Ben Franksen wrote: >> >> Am 21.12.20 um 19:54 schrieb Tom Ellis: >> > I think it's worth seeing more instances. As it is I don't understand >> > in what situations one would use these polymorphically and therefore >> > why `liftA2 (&&)`, `fmap not`, `pure True` and friends wouldn't >> > suffice. >> >> As with all overloading it's partly a matter of convenience. For >> instance you can't use 'liftA2 (&&)' as an operator. And your list of >> alternatives above demonstrates that one has to remember which lifting >> operator (pure, fmap, liftA2) to use, depending on arity. >> >> _______________________________________________ >> 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 casper at unbc.ca Tue Dec 22 01:17:24 2020 From: casper at unbc.ca (David Casperson) Date: Mon, 21 Dec 2020 17:17:24 -0800 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> <20201221185440.GE28742@cloudinit-builder> Message-ID: Hi all, let's start at lattices, a set with ∨ and ∧, where a∧(a∨b) ≈ a, a∨(a∧b) ≈ a, and ∨ and ∧ are commutative, associative, and idempotent. To get to Boolean algebras, we need to add a. bounds, b. distributivity, and c. complements. Given any lattice, you can always add a +∞ and a -∞ to get a bounded lattice (there is a functor ...). So I think that from the point of view of class structure Lattice and Bounded can exist independently. At least for lattices, upper and lower bounds are independent, so ??maybe?? a OneSidedBounded class. Not all lattices are distributive [i.e., they don't autmoatically satisfy a∧(c∨b) ≈ (a∧c)∨(a∧b), a∨(c∧b) ≈ (a∨c)∧(a∨b) ]. A class between lattice and DistributiveLattice that might be useful is ModularLattice (lattices with a notion of "height"). There are also meet semi-distributive ... (I'm not an expert on lattice theory, but I know several). Most people are most familiar with distributive lattices. Similarly, not all bounded distributive lattices have a complement operation. A bounded distributive lattice with a complement operation that satisfies De Morgan's laws and a′′≈a (alternatively a′∨a≈⊤) is a Boolean algebra. There is a strictly weaker notion of a Heyting algebra, which might be useful as a class, because it uses implication (→) as a fundamental operation in place of not (′). Usually in a Heyting algebra a′ is defined to mean a→⊥. There are Heyting algebras where a′∨a≈⊤ doesn't hold. As a programmer, I haven't seen a non-Boolean Heyting algebra in "the wild", or at least not recognized them, but it doesn't mean they wouldn't be useful. At any rate, these are some of the things that I would think about while simultaneously trying to avoid to much bikeshedding on the one hand, and suddenly forcefully retro-fitting Applicative (or Semigroup) on the other. hth, stay safe! Happy Solstice! David -- David Casperson Computer Science David Feuer, on 2020-12-21, you wrote: > From: David Feuer > To: Tikhon Jelvis > Date: Mon, 21 Dec 2020 15:49:18 > Cc: Ben Franksen , > Haskell Libraries > Subject: Re: type class Boolean > Message-ID: > > > CAUTION: This email is not from UNBC. Avoid links and attachments. Don't buy gift cards. > > > I imagine you'd want (&&) and (||) to live in a Lattice class, > `bottom` and `top` in `BoundedBelow` and `BoundedAbove`, respectively, > and `not` in a `Boolean` one. The relationship between Lattice, > JoinSemilattice, and MeetSemilattice is unfortunately awkward (much > like that between Ring, AbelianGroup, and Monoid), but mumble mumble > something. > > On Mon, Dec 21, 2020 at 6:32 PM Tikhon Jelvis wrote: >> >> For me, the most useful kind of instance would be symbolic booleans like SBV's SBool type. >> >> A real bonus would be making if-then-else polymorphic as well—although that doesn't really fit with the lattice abstraction. I know we can do that with RebindableSyntax, but that is a *heavyweight* extension to enable! >> >> Breaking boolean behavior up into a few different classes would work for this application. Boolean algebras for and/not/etc, Conditional for ifThenElse and maybe even Boolish or something for True and False pattern synonyms (or just true and false constants). >> >> I don't think all of this belongs in base, but making booleans and boolean operators more polymorphic would definitely be useful. >> >> On Mon, Dec 21, 2020 at 3:21 PM Ben Franksen wrote: >>> >>> Am 21.12.20 um 19:54 schrieb Tom Ellis: >>>> I think it's worth seeing more instances. As it is I don't understand >>>> in what situations one would use these polymorphically and therefore >>>> why `liftA2 (&&)`, `fmap not`, `pure True` and friends wouldn't >>>> suffice. >>> >>> As with all overloading it's partly a matter of convenience. For >>> instance you can't use 'liftA2 (&&)' as an operator. And your list of >>> alternatives above demonstrates that one has to remember which lifting >>> operator (pure, fmap, liftA2) to use, depending on arity. >>> >>> _______________________________________________ >>> 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 > From oleg.grenrus at iki.fi Tue Dec 22 10:40:26 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Tue, 22 Dec 2020 12:40:26 +0200 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> <1a647df1-f153-5e84-7b11-a74e6360bc14@iki.fi> Message-ID: <2dcd0dce-9342-45d6-e2ee-9983653726e9@iki.fi> I didn't want to clash with Prelude names. Also in Heyting-generality "not" is not correct either. (In general, neg is not involutive). - Oleg On 22.12.2020 1.28, Ben Franksen wrote: > Am 21.12.20 um 21:04 schrieb Oleg Grenrus: >> lattice package has 'not': >> https://hackage.haskell.org/package/lattices-2.0.2/docs/Algebra-Heyting.html#v:neg > Oh, nice! (Though 'neg' is not quite as suggestive as 'not'.) > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From oleg.grenrus at iki.fi Tue Dec 22 10:48:22 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Tue, 22 Dec 2020 12:48:22 +0200 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> <20201221185440.GE28742@cloudinit-builder> Message-ID: <4b26ef2b-2751-8d24-28df-8eacea45d644@iki.fi> You describe the lattices package. [1] - There is Lattice class with /\ and \/ - BoundedJoinSemiLattice and BoundedMeetSemiLattice with bottom and top - Heyting with ==> and neg I don't think that functionality should be part of base. The design is not clear and hard to agree on. There is also semilattices [2] package which takes different route There are no intermediate, additional Modular or Distributive or Boolean in lattices package, because these would be classes without members. I consider such a bad design in Haskell, so I omitted them. (Some people argue that there should be class Monoid m => CommutativeMonoid m, and there are plenty discussion why this is good or bad, or can be made ok). - Oleg [1] https://hackage.haskell.org/package/lattices [2] https://hackage.haskell.org/package/semilattices On 22.12.2020 3.17, David Casperson wrote: > Hi all, > > let's start at lattices, a set with ∨ and ∧, where a∧(a∨b) ≈ a, > a∨(a∧b) ≈ a, and ∨ and ∧ are commutative, associative, and > idempotent.  To get to Boolean algebras, we need to add > > a. bounds, > b. distributivity, and > c. complements. > > Given any lattice, you can always add a +∞ and a -∞ to get a > bounded lattice (there is a functor ...).  So I think that from > the point of view of class structure Lattice and Bounded can > exist independently.  At least for lattices, upper and lower > bounds are independent, so ??maybe?? a OneSidedBounded class. > > Not all lattices are distributive [i.e., they don't autmoatically > satisfy a∧(c∨b) ≈ (a∧c)∨(a∧b), a∨(c∧b) ≈ (a∨c)∧(a∨b) ].  A class > between lattice and DistributiveLattice that might be useful is > ModularLattice (lattices with a notion of "height").  There are > also meet semi-distributive ... (I'm not an expert on lattice > theory, but I know several).  Most people are most familiar with > distributive lattices. > > Similarly, not all bounded distributive lattices have a > complement operation.  A bounded distributive lattice with a > complement operation that satisfies De Morgan's laws and a′′≈a > (alternatively a′∨a≈⊤) is a Boolean algebra.  There is a strictly > weaker notion of a Heyting algebra, which might be useful as a > class, because it uses implication (→) as a fundamental operation > in place of not (′).  Usually in a Heyting algebra a′ is defined > to mean a→⊥.  There are Heyting algebras where a′∨a≈⊤ doesn't > hold. > > As a programmer, I haven't seen a non-Boolean Heyting algebra in > "the wild", or at least not recognized them, but it doesn't mean > they wouldn't be useful. > > At any rate, these are some of the things that I would think > about while simultaneously trying to avoid to much bikeshedding > on the one hand, and suddenly forcefully retro-fitting > Applicative (or Semigroup) on the other. > > hth, > > stay safe! > Happy Solstice! > > David > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From johannes.waldmann at htwk-leipzig.de Tue Dec 22 18:35:57 2020 From: johannes.waldmann at htwk-leipzig.de (Johannes Waldmann) Date: Tue, 22 Dec 2020 19:35:57 +0100 Subject: type class Boolean In-Reply-To: <8ef218f8-620d-3447-0db7-2783589675b1@htwk-leipzig.de> References: <8ef218f8-620d-3447-0db7-2783589675b1@htwk-leipzig.de> Message-ID: <3233bde9-f08a-f36c-993e-425a5d277a49@htwk-leipzig.de> [I sent this to -cafe by mistake] > most useful kind of instance would be symbolic booleans Yes. Ersatz has this: https://hackage.haskell.org/package/ersatz-0.4.8/docs/Ersatz-Bit.html#t:Boolean I also use this class (re-exported) in https://hackage.haskell.org/package/obdd Then modules typically start with import Prelude hiding ( not, and, or, (&&), (||) ) -- possibly more import Ersatz slightly annoying but you get used to it ... - J. From ben.franksen at online.de Tue Dec 22 19:40:21 2020 From: ben.franksen at online.de (Ben Franksen) Date: Tue, 22 Dec 2020 20:40:21 +0100 Subject: type class Boolean In-Reply-To: <2dcd0dce-9342-45d6-e2ee-9983653726e9@iki.fi> References: <20201221101237.GD28742@cloudinit-builder> <1a647df1-f153-5e84-7b11-a74e6360bc14@iki.fi> <2dcd0dce-9342-45d6-e2ee-9983653726e9@iki.fi> Message-ID: Am 22.12.20 um 11:40 schrieb Oleg Grenrus: > I didn't want to clash with Prelude names. Also in Heyting-generality > "not" is not correct either. (In general, neg is not involutive). Yes, obviously. I still think a class Boolean for boolean algebras (with the usual operators now limited to Bool) would be nice. I don't care too much whether it has HeytingAlgebra as super class or not, since I have never had any use for the more general classes. I think I mentioned in the beginning that my main motivation is convenience. Predicates are ubiquitous in programming and the desire to combine them using generalized boolean operators crops up almost everywhere. It amazes me how the designers of Haskell included this elaborate hierarchy of types and classes for all sorts of numbers in the standard libraries, but apparently never thought of generalizing booleans to predicates (and other boolean algebras). Cheers Ben From ietf-dane at dukhovni.org Wed Dec 23 06:32:38 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Wed, 23 Dec 2020 01:32:38 -0500 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? Message-ID: Is there a compelling reason for: sum = getSum #. foldMap' Sum product = getProduct #. foldMap' Product rather than: sum = foldl' (+) 0 product = foldl' (*) 1 A quick ghci session with today's GHC head yields: λ> import qualified Data.Foldable as F λ> :set +s λ> F.sum [0..10000000] 50000005000000 (2.98 secs, 1,612,368,368 bytes) λ> F.foldl' (+) 0 [0..10000000] 50000005000000 (0.28 secs, 880,065,112 bytes) The `foldl'` variant looks substantially more efficient (at least for lists), is there some important context in which `foldMap'` is preferable? -- Viktor. From ietf-dane at dukhovni.org Wed Dec 23 08:19:51 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Wed, 23 Dec 2020 06:19:51 -0200 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: Message-ID: > On Dec 20, 2020, at 8:15 PM, Viktor Dukhovni wrote: > > I am asking because I am writing some expository prose for > Data.Foldable, to go at the bottom of the document, structurally along > the lines of what I contributed for Data.Traversable, but with a fairly > different focus. The goal is draw careful distinctions between > strict recursive and lazy corecursive reductions, explaining their > proper usage and typical implementations. The draft version can be seen at: https://imrryr.org/~viktor/haskell/foldable-doc/Data-Foldable.html along with a pre-formatted Data.Traversable (already merged some months back, but may not yet be easy to found in formatted form): https://imrryr.org/~viktor/haskell/foldable-doc/Data-Traversable.html Any feedback appreciated... Is this roughly ready for an MR, or are there any changes that are needed first and best discussed on the list rather than via Gitlab? -- Viktor. From tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk Wed Dec 23 09:58:41 2020 From: tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk (Tom Ellis) Date: Wed, 23 Dec 2020 09:58:41 +0000 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: References: Message-ID: <20201223095841.GH28742@cloudinit-builder> On Wed, Dec 23, 2020 at 01:32:38AM -0500, Viktor Dukhovni wrote: > Is there a compelling reason for: > > sum = getSum #. foldMap' Sum > product = getProduct #. foldMap' Product > > rather than: > > sum = foldl' (+) 0 > product = foldl' (*) 1 [...] > The `foldl'` variant looks substantially more efficient (at least for > lists), is there some important context in which `foldMap'` is > preferable? Have you benchmarked with optimisations on? I would not be surprised if a small amount of inlining brings them to the same speed. Tom From oleg.grenrus at iki.fi Wed Dec 23 10:44:06 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Wed, 23 Dec 2020 12:44:06 +0200 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: References: Message-ID: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> Because the related change proposal(s) are never accepted nor implemented. Most recent one is quite recent though. https://mail.haskell.org/pipermail/libraries/2020-October/030862.html - Oleg On 23.12.2020 8.32, Viktor Dukhovni wrote: > Is there a compelling reason for: > > sum = getSum #. foldMap' Sum > product = getProduct #. foldMap' Product > > rather than: > > sum = foldl' (+) 0 > product = foldl' (*) 1 > > A quick ghci session with today's GHC head yields: > > λ> import qualified Data.Foldable as F > λ> :set +s > > λ> F.sum [0..10000000] > 50000005000000 > (2.98 secs, 1,612,368,368 bytes) > > λ> F.foldl' (+) 0 [0..10000000] > 50000005000000 > (0.28 secs, 880,065,112 bytes) > > The `foldl'` variant looks substantially more efficient (at least for > lists), is there some important context in which `foldMap'` is > preferable? > From oleg.grenrus at iki.fi Wed Dec 23 12:55:45 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Wed, 23 Dec 2020 14:55:45 +0200 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> References: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> Message-ID: <3d0e3396-2f06-a9b2-7a11-bddf0abbf6b4@iki.fi> I stand corrected. https://gitlab.haskell.org/ghc/ghc/-/merge_requests/4355 is merged and seems I misread the original e-mail. Foldable should prefer foldMap' (or foldMap) because it offers most opportunities (Monoid mappend is associative). Trees, SnocList work better by default. For lists the implementation could use foldl', because in that special case it makes more sense. These methods (sum, product) are part of Foldable class specifically so they can be overriden. - Oleg On 23.12.2020 12.44, Oleg Grenrus wrote: > Because the related change proposal(s) are never accepted nor implemented. > > Most recent one is quite recent though. > https://mail.haskell.org/pipermail/libraries/2020-October/030862.html > > - Oleg > > On 23.12.2020 8.32, Viktor Dukhovni wrote: >> Is there a compelling reason for: >> >> sum = getSum #. foldMap' Sum >> product = getProduct #. foldMap' Product >> >> rather than: >> >> sum = foldl' (+) 0 >> product = foldl' (*) 1 >> >> A quick ghci session with today's GHC head yields: >> >> λ> import qualified Data.Foldable as F >> λ> :set +s >> >> λ> F.sum [0..10000000] >> 50000005000000 >> (2.98 secs, 1,612,368,368 bytes) >> >> λ> F.foldl' (+) 0 [0..10000000] >> 50000005000000 >> (0.28 secs, 880,065,112 bytes) >> >> The `foldl'` variant looks substantially more efficient (at least for >> lists), is there some important context in which `foldMap'` is >> preferable? >> > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From merijn at inconsistent.nl Wed Dec 23 13:08:51 2020 From: merijn at inconsistent.nl (Merijn Verstraaten) Date: Wed, 23 Dec 2020 14:08:51 +0100 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: <3d0e3396-2f06-a9b2-7a11-bddf0abbf6b4@iki.fi> References: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> <3d0e3396-2f06-a9b2-7a11-bddf0abbf6b4@iki.fi> Message-ID: Also, note that the benchmark from the original email: 1) uses ghci, rendering it meaningless as it's not remotely representative of performance of compiled code 2) uses the list instance of Foldable which does *not* use the defaults shown in the original email, but uses explicit definitions. The foldMap' code shown (but not used!) *is* strict, so would, presumably perform comparably to foldl'. Unlike the foldl version of sum that Foldable for lists currently uses. Cheers, Merijn > On 23 Dec 2020, at 13:55, Oleg Grenrus wrote: > > I stand corrected. > https://gitlab.haskell.org/ghc/ghc/-/merge_requests/4355 is merged > > and seems I misread the original e-mail. > > Foldable should prefer foldMap' (or foldMap) because it offers most > opportunities (Monoid mappend is associative). Trees, SnocList work > better by default. > > For lists the implementation could use foldl', because in that special > case it makes more sense. > > These methods (sum, product) are part of Foldable class specifically so > they can be overriden. > > - Oleg > > On 23.12.2020 12.44, Oleg Grenrus wrote: >> Because the related change proposal(s) are never accepted nor implemented. >> >> Most recent one is quite recent though. >> https://mail.haskell.org/pipermail/libraries/2020-October/030862.html >> >> - Oleg >> >> On 23.12.2020 8.32, Viktor Dukhovni wrote: >>> Is there a compelling reason for: >>> >>> sum = getSum #. foldMap' Sum >>> product = getProduct #. foldMap' Product >>> >>> rather than: >>> >>> sum = foldl' (+) 0 >>> product = foldl' (*) 1 >>> >>> A quick ghci session with today's GHC head yields: >>> >>> λ> import qualified Data.Foldable as F >>> λ> :set +s >>> >>> λ> F.sum [0..10000000] >>> 50000005000000 >>> (2.98 secs, 1,612,368,368 bytes) >>> >>> λ> F.foldl' (+) 0 [0..10000000] >>> 50000005000000 >>> (0.28 secs, 880,065,112 bytes) >>> >>> The `foldl'` variant looks substantially more efficient (at least for >>> lists), is there some important context in which `foldMap'` is >>> preferable? >>> >> _______________________________________________ >> 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 -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: Message signed with OpenPGP URL: From evincarofautumn at gmail.com Wed Dec 23 21:40:31 2020 From: evincarofautumn at gmail.com (Jon Purdy) Date: Wed, 23 Dec 2020 13:40:31 -0800 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: Just as a point of reference in the design space, some of which has already been brought up, PureScript does this with its ‘HeytingAlgebra’ class[1], which also includes implication. Booleans and predicates are both instances. class HeytingAlgebra a where ff :: a tt :: a implies :: a -> a -> a conj :: a -> a -> a -- aliased to (&&) disj :: a -> a -> a -- aliased to (||) not :: a -> a This has the standard laws for a Heyting algebra: AND and OR are associative, commutative, and idempotent; implication is also idempotent; true and false are identities for AND and OR, respectively; AND and OR are related by absorption; implication distributes over AND, and the following whose names (if they are named) I don’t actually know: a && (a `implies` b) = a && b b && (a `implies` b) = b not a = a `implies` ff As bikesheds go, I prefer your names ‘top’ and ‘bottom’ over ‘tt’ and ‘ff’; generalising ‘(&&)’ and ‘(||)’ is fine if it doesn’t cause ambiguity issues, otherwise I like ‘(/\)’ and ‘(\/)’—which, after all, are the very reason the backslash was added to ASCII in the first place. [1] https://pursuit.purescript.org/packages/purescript-prelude/4.1.1/docs/Data.HeytingAlgebra On Mon, Dec 21, 2020 at 10:20 AM Ben Franksen wrote: > All this talk about lattices reminds me of one of my pet gripes I have > with the standard libraries (base), namely that the boolean operators > aren't overloaded. I don't want to open endless discussions about the > perfect generalization, because there are lots of valid generalizations > and the lattice package is fine for those. > > But most generalizations don't have a 'not' (complement) operator. So, a > simple type class Boolean with instances for Bool and functions > returning Booleans should cover the majority of use cases; more > instances could be added of course. Something like > > {-# LANGUAGE NoImplicitPrelude #-} > module Data.Boolean where > > import Prelude hiding ((&&),(||),not) > import qualified Prelude > > infixr 3 && > infixr 2 || > > class Boolean a where > -- laws: that of a boolean algebra, i.e. > -- complemented distributive lattice, see > -- https://en.wikipedia.org/wiki/Boolean_algebra#Laws > (&&) :: a -> a -> a > (||) :: a -> a -> a > not :: a -> a > top :: a > bottom :: a > > instance Boolean Bool where > (&&) = (Prelude.&&) > (||) = (Prelude.||) > not = Prelude.not > top = True > bottom = False > > instance Boolean b => Boolean (a->b) where > (f && g) x = f x && g x > (f || g) x = f x || g x > (not f) x = not (f x) > top = const top > bottom = const bottom > > IMHO this would be absolutely benign, no problems with type inference, > fully Haskell98, no breakage of existing code I can think of. (I didn't > check that last point but I would be very surprised if there were.) > > Cheers > Ben > > Am 21.12.20 um 17:14 schrieb Carter Schonwald: > > edit: neglected to mention that choosing which lattice (and or dual) to > use > > only really matters when considering products/sums of lattices to form > new > > lattices > > > > On Mon, Dec 21, 2020 at 11:12 AM Carter Schonwald < > > carter.schonwald at gmail.com> wrote: > > > >> why are we equating the lattice operators for True and false with the > >> lattice operators for set? (for both structures, we have the dual > partial > >> order is also a lattice, so unless we have ) > >> (i'm going to get the names of these equations wrong, but ) > >> > >> the "identity" law is going to be max `intersect` y == y , min > `union` y > >> === y > >> > >> the "absorbing" law is going to be min `intersect` y == min , max > >> `union` y == max > >> > >> these rules work the same for (min = emptyset, max == full set, union == > >> set union, intersect == set intersecct) > >> OR for its dual lattice (min == full set, max == emtpy set, union = set > >> intersection, intersect == set union) > >> > >> at some level arguing about the empty list case turns into artifacts of > >> "simple" definitions > >> > >> that said, i suppose a case could be made that for intersect :: [a] -> > a , > >> that as the list argument gets larger the result should be getting > >> *smaller*, so list intersect of lattice elements should be > "anti-monotone", > >> and list union should be monotone (the result gets bigger). I dont > usually > >> see tht > >> > >> either way, I do strongly feel that either way, arguing by how we choose > >> to relate the boolean lattice and seet lattices is perhaps the wrong > >> choice... because both lattices are equivalent to theeir dual lattice > >> > >> On Mon, Dec 21, 2020 at 5:12 AM Tom Ellis < > >> tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk> wrote: > >> > >>> On Sun, Dec 20, 2020 at 11:05:39PM +0100, Ben Franksen wrote: > >>>> Am 06.12.20 um 19:58 schrieb Sven Panne: > >>>>> To me it's just the other way around: It violates aesthetics if it > >>> doesn't > >>>>> follow the mathematical definition in all cases, which is why I don't > >>> like > >>>>> NonEmpty here. > >>>> > >>>> I think you've got that wrong. > >>>> > >>>> x `elem` intersections [] > >>>> = {definition} > >>>> forall xs in []. x `elem` xs > >>>> = {vacuous forall} > >>>> true > >>>> > >>>> Any proposition P(x) is true for all x in []. So the mathematical > >>>> definition of intersections::[Set a]-> Set a would not be the empty > set > >>>> but the set of all x:a, which in general we have no way to construct. > >>> > >>> Yes, and to bring this back to Sven's original claim > >>> > >>> | Why NonEmpty? I would expect "intersections [] = Set.empty", because > >>> | the result contains all the elements which are in all sets, > >>> | i.e. none. That's at least my intuition, is there some law which > >>> | this would violate? > >>> > >>> the correct definition of "intersections []" should be "all elements > >>> which are in all of no sets" i.e. _every_ value of the given type! > >>> > >>> Tom > >>> _______________________________________________ > >>> 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 > -------------- next part -------------- An HTML attachment was scrubbed... URL: From ietf-dane at dukhovni.org Wed Dec 23 21:52:00 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Wed, 23 Dec 2020 16:52:00 -0500 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: References: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> <3d0e3396-2f06-a9b2-7a11-bddf0abbf6b4@iki.fi> Message-ID: On Wed, Dec 23, 2020 at 02:08:51PM +0100, Merijn Verstraaten wrote: > Also, note that the benchmark from the original email: > 1) uses ghci, rendering it meaningless as it's not remotely > representative of performance of compiled code While indeed List does not use the default definition, when that definition is used for List, the results with optimised compiled code are even more stark. When summing [0..1_000_000_000] using the foldMap'-based definition of `sum`: main :: IO () main = getArgs >>= \case [n] -> go (read n) _ -> go 1_000_000_000 where go :: Int -> IO () go n = print $ getSum #. F.foldMap' Sum $ [0..n] The list elements end up allocated on the heap and I get: $ ./sum1 +RTS -s 500000000500000000 72,000,051,888 bytes allocated in the heap 571,120 bytes copied during GC 44,376 bytes maximum residency (2 sample(s)) 29,352 bytes maximum slop 5 MiB total memory in use (0 MB lost due to fragmentation) INIT time 0.000s ( 0.000s elapsed) MUT time 6.996s ( 6.988s elapsed) GC time 0.036s ( 0.043s elapsed) EXIT time 0.000s ( 0.002s elapsed) Total time 7.033s ( 7.034s elapsed) while with the List instance of foldl': main :: IO () main = getArgs >>= \case [n] -> go (read n) _ -> go 1_000_000_000 where go :: Int -> IO () go n = print $ F.foldl' (+) 0 $ [0..n] the computation avoids heap allocation: $ ./sum2 +RTS -s 500000000500000000 51,816 bytes allocated in the heap 3,320 bytes copied during GC 44,376 bytes maximum residency (1 sample(s)) 25,256 bytes maximum slop 5 MiB total memory in use (0 MB lost due to fragmentation) INIT time 0.000s ( 0.000s elapsed) MUT time 0.346s ( 0.346s elapsed) GC time 0.001s ( 0.001s elapsed) EXIT time 0.000s ( 0.004s elapsed) Total time 0.347s ( 0.351s elapsed) > 2) uses the list instance of Foldable which does *not* use the > defaults shown in the original email, but uses explicit definitions. Yes, the "List" instance of `sum` does not use the default definition. That instance shows comparable performance for `sum` and `foldl'` when compiled optimised. > The foldMap' code shown (but not used!) *is* strict, so would, > presumably perform comparably to foldl'. Unlike the foldl version of > sum that Foldable for lists currently uses. So my question is basically whether the default is *generally* the more appropriate choice. It clearly is not the more efficient choice for Lists (more precisely, lazily generated iterators). The difference mostly goes away when the data structure in question is already fully realised in memory (as with e.g. strict maps, ...) But I am skeptical that the `foldMap'` defintion is a better default, are there real cases where it is actually better? -- Viktor. From keith.wygant at gmail.com Thu Dec 24 00:25:45 2020 From: keith.wygant at gmail.com (Keith) Date: Thu, 24 Dec 2020 00:25:45 +0000 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: References: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> <3d0e3396-2f06-a9b2-7a11-bddf0abbf6b4@iki.fi> Message-ID: There's no benefit to optimizing default Foldable methods for data types that already have specialized methods. foldMap' does not care about the nesting of the structure like foldl', so it's a better default choice. What I worry more about is that getSum . foldl' (\ z x -> z <> Sum x) mempty is compiling to different code than foldl' (+) 0. — Sent from my phone with K-9 Mail. On December 23, 2020 9:52:00 PM UTC, Viktor Dukhovni wrote: >On Wed, Dec 23, 2020 at 02:08:51PM +0100, Merijn Verstraaten wrote: > >> Also, note that the benchmark from the original email: >> 1) uses ghci, rendering it meaningless as it's not remotely >> representative of performance of compiled code > >While indeed List does not use the default definition, when that >definition is used for List, the results with optimised compiled code >are even more stark. When summing [0..1_000_000_000] using the >foldMap'-based definition of `sum`: > > main :: IO () > main = getArgs >>= \case > [n] -> go (read n) > _ -> go 1_000_000_000 > where > go :: Int -> IO () > go n = print $ getSum #. F.foldMap' Sum $ [0..n] > >The list elements end up allocated on the heap and I get: > > $ ./sum1 +RTS -s > 500000000500000000 > 72,000,051,888 bytes allocated in the heap > 571,120 bytes copied during GC > 44,376 bytes maximum residency (2 sample(s)) > 29,352 bytes maximum slop > 5 MiB total memory in use (0 MB lost due to fragmentation) > > INIT time 0.000s ( 0.000s elapsed) > MUT time 6.996s ( 6.988s elapsed) > GC time 0.036s ( 0.043s elapsed) > EXIT time 0.000s ( 0.002s elapsed) > Total time 7.033s ( 7.034s elapsed) > >while with the List instance of foldl': > > main :: IO () > main = getArgs >>= \case > [n] -> go (read n) > _ -> go 1_000_000_000 > where > go :: Int -> IO () > go n = print $ F.foldl' (+) 0 $ [0..n] > >the computation avoids heap allocation: > > $ ./sum2 +RTS -s > 500000000500000000 > 51,816 bytes allocated in the heap > 3,320 bytes copied during GC > 44,376 bytes maximum residency (1 sample(s)) > 25,256 bytes maximum slop > 5 MiB total memory in use (0 MB lost due to fragmentation) > > INIT time 0.000s ( 0.000s elapsed) > MUT time 0.346s ( 0.346s elapsed) > GC time 0.001s ( 0.001s elapsed) > EXIT time 0.000s ( 0.004s elapsed) > Total time 0.347s ( 0.351s elapsed) > >> 2) uses the list instance of Foldable which does *not* use the >> defaults shown in the original email, but uses explicit definitions. > >Yes, the "List" instance of `sum` does not use the default definition. >That instance shows comparable performance for `sum` and `foldl'` when >compiled optimised. > >> The foldMap' code shown (but not used!) *is* strict, so would, >> presumably perform comparably to foldl'. Unlike the foldl version of >> sum that Foldable for lists currently uses. > >So my question is basically whether the default is *generally* the more >appropriate choice. It clearly is not the more efficient choice for >Lists (more precisely, lazily generated iterators). > >The difference mostly goes away when the data structure in question is >already fully realised in memory (as with e.g. strict maps, ...) > >But I am skeptical that the `foldMap'` defintion is a better default, >are there real cases where it is actually better? > >-- > Viktor. >_______________________________________________ >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 Thu Dec 24 00:42:44 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 23 Dec 2020 19:42:44 -0500 Subject: Improve documentation for Real Message-ID: The Real class has one method: -- | the rational equivalent of its real argument with full precision toRational :: a -> Rational This is ... pretty weird. What does "full precision" mean? For integral and floating point types, it's fine. It's not at all meaningful for 1. Computable reals 2. Real algebraic numbers 3. Real numbers expressible in radicals 4. Rational numbers augmented with some extra numbers like pi 5. Geometrically constructable reals 6. Etc. Can we settle on a meaning for toRational? The properFraction method of the RealFrac class has basically the same issue. -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Thu Dec 24 01:02:33 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Thu, 24 Dec 2020 02:02:33 +0100 (CET) Subject: Improve documentation for Real In-Reply-To: References: Message-ID: On Wed, 23 Dec 2020, David Feuer wrote: > The Real class has one method: > -- | the rational equivalent of its real argument with full precision > > toRational :: a -> Rational > > This is ... pretty weird. What does "full precision" mean? For integral and floating point types, it's fine. It's > not at all meaningful for > > 1. Computable reals > 2. Real algebraic numbers > 3. Real numbers expressible in radicals > 4. Rational numbers augmented with some extra numbers like pi > 5. Geometrically constructable reals > 6. Etc. They cannot have Real instances, then. Right? From david.feuer at gmail.com Thu Dec 24 01:06:01 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 23 Dec 2020 20:06:01 -0500 Subject: Improve documentation for Real In-Reply-To: References: Message-ID: Perhaps that's the answer, but it seems frankly bizarre to call a class Real if `Real s` actually means that `s` is a subset of the rational numbers. On Wed, Dec 23, 2020, 8:02 PM Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Wed, 23 Dec 2020, David Feuer wrote: > > > The Real class has one method: > > -- | the rational equivalent of its real argument with full precision > > > > toRational :: a -> Rational > > > > This is ... pretty weird. What does "full precision" mean? For integral > and floating point types, it's fine. It's > > not at all meaningful for > > > > 1. Computable reals > > 2. Real algebraic numbers > > 3. Real numbers expressible in radicals > > 4. Rational numbers augmented with some extra numbers like pi > > 5. Geometrically constructable reals > > 6. Etc. > > They cannot have Real instances, then. Right? > -------------- next part -------------- An HTML attachment was scrubbed... URL: From chessai1996 at gmail.com Thu Dec 24 01:19:37 2020 From: chessai1996 at gmail.com (chessai) Date: Wed, 23 Dec 2020 19:19:37 -0600 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: References: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> <3d0e3396-2f06-a9b2-7a11-bddf0abbf6b4@iki.fi> Message-ID: On mobile, but I don't see how you're compiling? Is it at least with -O1? On Wed, Dec 23, 2020, 18:26 Keith wrote: > There's no benefit to optimizing default Foldable methods for data types > that already have specialized methods. > > foldMap' does not care about the nesting of the structure like foldl', so > it's a better default choice. > > What I worry more about is that getSum . foldl' (\ z x -> z <> Sum x) > mempty is compiling to different code than foldl' (+) 0. > — > Sent from my phone with K-9 Mail. > > On December 23, 2020 9:52:00 PM UTC, Viktor Dukhovni < > ietf-dane at dukhovni.org> wrote: >> >> On Wed, Dec 23, 2020 at 02:08:51PM +0100, Merijn Verstraaten wrote: >> >> Also, note that the benchmark from the original email: >>> 1) uses ghci, rendering it meaningless as it's not remotely >>> representative of performance of compiled code >>> >> >> While indeed List does not use the default definition, when that >> definition is used for List, the results with optimised compiled code >> are even more stark. When summing [0..1_000_000_000] using the >> foldMap'-based definition of `sum`: >> >> main :: IO () >> main = getArgs >>= \case >> [n] -> go (read n) >> _ -> go 1_000_000_000 >> where >> go :: Int -> IO () >> go n = print $ getSum #. F.foldMap' Sum $ [0..n] >> >> The list elements end up allocated on the heap and I get: >> >> $ ./sum1 +RTS -s >> 500000000500000000 >> 72,000,051,888 bytes allocated in the heap >> 571,120 bytes copied during GC >> 44,376 bytes maximum residency (2 sample(s)) >> 29,352 bytes maximum slop >> 5 MiB total memory in use (0 MB lost due to fragmentation) >> >> INIT time 0.000s ( 0.000s elapsed) >> MUT time 6.996s ( 6.988s elapsed) >> GC time 0.036s ( 0.043s elapsed) >> EXIT time 0.000s ( 0.002s elapsed) >> Total time 7.033s ( 7.034s elapsed) >> >> while with the List instance of foldl': >> >> main :: IO () >> main = getArgs >>= \case >> [n] -> go (read n) >> _ -> go 1_000_000_000 >> where >> go :: Int -> IO () >> go n = print $ F.foldl' (+) 0 $ [0..n] >> >> the computation avoids heap allocation: >> >> $ ./sum2 +RTS -s >> 500000000500000000 >> 51,816 bytes allocated in the heap >> 3,320 bytes copied during GC >> 44,376 bytes maximum residency (1 sample(s)) >> 25,256 bytes maximum slop >> 5 MiB total memory in use (0 MB lost due to fragmentation) >> >> INIT time 0.000s ( 0.000s elapsed) >> MUT time 0.346s ( 0.346s elapsed) >> GC time 0.001s ( 0.001s elapsed) >> EXIT time 0.000s ( 0.004s elapsed) >> Total time 0.347s ( 0.351s elapsed) >> >> 2) uses the list instance of Foldable which does *not* use the >>> defaults shown in the original email, but uses explicit definitions. >>> >> >> Yes, the "List" instance of `sum` does not use the default definition. >> That instance shows comparable performance for `sum` and `foldl'` when >> compiled optimised. >> >> The foldMap' code shown (but not used!) *is* strict, so would, >>> presumably perform comparably to foldl'. Unlike the foldl version of >>> sum that Foldable for lists currently uses. >>> >> >> So my question is basically whether the default is *generally* the more >> appropriate choice. It clearly is not the more efficient choice for >> Lists (more precisely, lazily generated iterators). >> >> The difference mostly goes away when the data structure in question is >> already fully realised in memory (as with e.g. strict maps, ...) >> >> But I am skeptical that the `foldMap'` defintion is a better default, >> are there real cases where it is actually better? >> >> _______________________________________________ > 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 ietf-dane at dukhovni.org Thu Dec 24 01:41:03 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Wed, 23 Dec 2020 20:41:03 -0500 Subject: Why are `sum` and `product` defined via foldMap' and not foldl'? In-Reply-To: References: <86494e64-762b-1878-da54-84d937a0cd32@iki.fi> <3d0e3396-2f06-a9b2-7a11-bddf0abbf6b4@iki.fi> Message-ID: On Wed, Dec 23, 2020 at 07:19:37PM -0600, chessai wrote: > On mobile, but I don't see how you're compiling? Is it at least with -O1? > > On Wed, Dec 23, 2020, 18:26 Keith wrote: > > > There's no benefit to optimizing default Foldable methods for data types > > that already have specialized methods. > > > > foldMap' does not care about the nesting of the structure like foldl', so > > it's a better default choice. > > > > What I worry more about is that getSum . foldl' (\ z x -> z <> Sum x) > > mempty is compiling to different code than foldl' (+) 0. Well, perhaps the same sort of "lifting" concerns that motivated: getSum #. foldMap' Sum in the default definition. With (#.) just ignoring the `getSum` and pretending that foldMap' already returns the correct result. FWIW, my builds were with "-O2". -- Viktor. From david.feuer at gmail.com Thu Dec 24 02:46:29 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 23 Dec 2020 21:46:29 -0500 Subject: Improve documentation for Real In-Reply-To: References: Message-ID: Wouldn't it make more sense to get at the idea from another direction or two? One obvious idea is to compare to a rational number: compareRational :: a -> Rational -> Ordering Neither this nor Ord can be supported by computable reals, so maybe there should be a superclass for numbers that can be *approximated by* rationals to an arbitrary precise degree. On Wed, Dec 23, 2020, 8:06 PM David Feuer wrote: > Perhaps that's the answer, but it seems frankly bizarre to call a class > Real if `Real s` actually means that `s` is a subset of the rational > numbers. > > On Wed, Dec 23, 2020, 8:02 PM Henning Thielemann < > lemming at henning-thielemann.de> wrote: > >> >> On Wed, 23 Dec 2020, David Feuer wrote: >> >> > The Real class has one method: >> > -- | the rational equivalent of its real argument with full precision >> > >> > toRational :: a -> Rational >> > >> > This is ... pretty weird. What does "full precision" mean? For integral >> and floating point types, it's fine. It's >> > not at all meaningful for >> > >> > 1. Computable reals >> > 2. Real algebraic numbers >> > 3. Real numbers expressible in radicals >> > 4. Rational numbers augmented with some extra numbers like pi >> > 5. Geometrically constructable reals >> > 6. Etc. >> >> They cannot have Real instances, then. Right? >> > -------------- next part -------------- An HTML attachment was scrubbed... URL: From simon.jakobi at googlemail.com Thu Dec 24 04:25:34 2020 From: simon.jakobi at googlemail.com (Simon Jakobi) Date: Thu, 24 Dec 2020 05:25:34 +0100 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: Message-ID: Hi Victor! Thanks for this initiative! I think it would be great to have some good, in-depth documentation on Foldable and Traversable in base! So far I've made a pass over the Foldable docs. Here are some random comments: * I think the docs at the bottom of the page are easy to miss. Maybe add a reference to them at the top of the page. * I think the documentation might be more accessible and inviting if it would use slightly simpler language. For example the first sentence of the overview section: The Foldable class encompasses structures that support element-wise reduction to a summary value. With words like "encompass" and "summary" (as an adjective) the sentence sounds slightly off-putting to me – this might be a matter of taste though. * In the code example for computing an average, a proper declaration might be easier to follow: average :: (Foldable f, Fractional a) => f a -> a * A clearer name for the "Construction" section might be "Defining instances" * The distinction between recursive and corecursive reduction looks very valuable IMHO! Cheers! Simon Am Mi., 23. Dez. 2020 um 09:20 Uhr schrieb Viktor Dukhovni : > > > On Dec 20, 2020, at 8:15 PM, Viktor Dukhovni wrote: > > > > I am asking because I am writing some expository prose for > > Data.Foldable, to go at the bottom of the document, structurally along > > the lines of what I contributed for Data.Traversable, but with a fairly > > different focus. The goal is draw careful distinctions between > > strict recursive and lazy corecursive reductions, explaining their > > proper usage and typical implementations. > > The draft version can be seen at: > > https://imrryr.org/~viktor/haskell/foldable-doc/Data-Foldable.html > > along with a pre-formatted Data.Traversable (already merged some > months back, but may not yet be easy to found in formatted form): > > https://imrryr.org/~viktor/haskell/foldable-doc/Data-Traversable.html > > Any feedback appreciated... Is this roughly ready for an MR, or are there > any changes that are needed first and best discussed on the list rather > than via Gitlab? > > -- > Viktor. > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From ietf-dane at dukhovni.org Thu Dec 24 05:42:09 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Thu, 24 Dec 2020 00:42:09 -0500 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: Message-ID: On Thu, Dec 24, 2020 at 05:25:34AM +0100, Simon Jakobi via Libraries wrote: > Hi Victor! > > Thanks for this initiative! I think it would be great to have some > good, in-depth documentation on Foldable and Traversable in base! Thanks for the encouragement. FWIW, the Traversable writeup (module a reference URL update), is already in base (for 9.0), but if you find things worth fixing, there may yet be time to get some of those done. > * I think the docs at the bottom of the page are easy to miss. Maybe > add a reference to them at the top of the page. Done. > * I think the documentation might be more accessible and inviting if > it would use slightly simpler language. For example the first sentence > of the overview section: I made some effort to simplify the language. I hope it is better. > * In the code example for computing an average, a proper declaration > might be easier to follow: > > average :: (Foldable f, Fractional a) => f a -> a Done. > * A clearer name for the "Construction" section might be "Defining instances" Done. Thanks. > * The distinction between recursive and corecursive reduction looks > very valuable IMHO! I'm glad you like it. For me, writing this down was actually the main motivation for the new text. I wanted to understand it better, and this seemed like the best way. :-) Let me know when you think this is close enough to being ready to move the final polish discussion to Gitlab. -- Viktor. From godzbanebane at gmail.com Thu Dec 24 08:21:47 2020 From: godzbanebane at gmail.com (Georgi Lyubenov) Date: Thu, 24 Dec 2020 10:21:47 +0200 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: Message-ID: In the "lazy corecursive" section from your original links, you mention a "flatten" function, but then the next function is named "toList". I think this might be an oversight. ======= Georgi -------------- next part -------------- An HTML attachment was scrubbed... URL: From ietf-dane at dukhovni.org Thu Dec 24 21:22:38 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Thu, 24 Dec 2020 16:22:38 -0500 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: Message-ID: <20201224212238.GO1459@straasha.imrryr.org> On Wed, Dec 23, 2020 at 06:19:51AM -0200, Viktor Dukhovni wrote: > The draft version can be seen at: > > https://imrryr.org/~viktor/haskell/foldable-doc/Data-Foldable.html > > along with a pre-formatted Data.Traversable (already merged some > months back, but may not yet be easy to found in formatted form): > > https://imrryr.org/~viktor/haskell/foldable-doc/Data-Traversable.html > > Any feedback appreciated... Is this roughly ready for an MR, or are there > any changes that are needed first and best discussed on the list rather > than via Gitlab? I've integrated the suggestions posted so far, and added sections that list all the strict and all the lazy functions together describing briefly their common features. If the overall approach is sound, it might perhaps now make sense to add some brief text also in each function synopsis that classifies it as strict recursive, lazy corecursive, or some hybrid. But perhaps just having that level of detail at the bottom is sufficient? -- Viktor. From ietf-dane at dukhovni.org Fri Dec 25 08:04:42 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Fri, 25 Dec 2020 06:04:42 -0200 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: <20201224212238.GO1459@straasha.imrryr.org> References: <20201224212238.GO1459@straasha.imrryr.org> Message-ID: > On Dec 24, 2020, at 7:22 PM, Viktor Dukhovni wrote: > > If the overall approach is sound, it might perhaps now make sense to add > some brief text also in each function synopsis that classifies it as > strict recursive, lazy corecursive, or some hybrid. But perhaps just > having that level of detail at the bottom is sufficient? I've forked the document to explore carving out a third-class of folds, the *short-circuit* folds, that though they also are based on `foldr`, are not really corecursive, they just might terminate early, but produce only a single final result. This variant is at: Is the new version heading in the right direction? Is anyone interested in helping out to get the initial draft in good enough shape for an MR? -- Viktor. From ben.franksen at online.de Sun Dec 27 10:03:37 2020 From: ben.franksen at online.de (Ben Franksen) Date: Sun, 27 Dec 2020 11:03:37 +0100 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: Am 23.12.20 um 22:40 schrieb Jon Purdy: > otherwise I like ‘(/\)’ and ‘(\/)’—which, after all, are the very > reason the backslash was added to ASCII in the first place. Interesting. Out of curiosity: do you have a reference for this? Cheers Ben From ben.franksen at online.de Sun Dec 27 10:20:00 2020 From: ben.franksen at online.de (Ben Franksen) Date: Sun, 27 Dec 2020 11:20:00 +0100 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: <20201224212238.GO1459@straasha.imrryr.org> Message-ID: Am 25.12.20 um 09:04 schrieb Viktor Dukhovni: >> On Dec 24, 2020, at 7:22 PM, Viktor Dukhovni wrote: >> >> If the overall approach is sound, it might perhaps now make sense to add >> some brief text also in each function synopsis that classifies it as >> strict recursive, lazy corecursive, or some hybrid. But perhaps just >> having that level of detail at the bottom is sufficient? > > I've forked the document to explore carving out a third-class > of folds, the *short-circuit* folds, that though they also > are based on `foldr`, are not really corecursive, they just > might terminate early, but produce only a single final result. > > This variant is at: The original is at: > > Is the new version heading in the right direction? Is anyone interested > in helping out to get the initial draft in good enough shape for an MR? One minor nitpick: Short-circuit reduction, which examines some initial sequence of the input elements, but stops once a termination condition is met, returning a final result based only on the elements considered to that point. The ^ up This one should really be fixed: remaining elements are not considered. The input should generally be finite, because the termination condition but otherwise be never met. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ hard to understand because of grammar mistakes Otherwise: very well written. Why are the class laws part of the Overview and not of the class documentation proper as usual? Cheers Ben From ietf-dane at dukhovni.org Sun Dec 27 10:31:31 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 27 Dec 2020 05:31:31 -0500 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: <20201224212238.GO1459@straasha.imrryr.org> Message-ID: On Sun, Dec 27, 2020 at 11:20:00AM +0100, Ben Franksen wrote: > > This variant is at: > The original is at: > > > > Is the new version heading in the right direction? Is anyone interested > > in helping out to get the initial draft in good enough shape for an MR? > > One minor nitpick: > > Short-circuit reduction, which examines some initial sequence of the > input elements, but stops once a termination condition is met, returning > a final result based only on the elements considered to that point. The > ^ up > > This one should really be fixed: > > remaining elements are not considered. The input should generally be > finite, because the termination condition but otherwise be never met. > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > hard to understand because of grammar mistakes > > Otherwise: very well written. Thanks, while reworking it, some things gone mangled, and I haven't finished the proofreading yet. I'll fix these pronto. > Why are the class laws part of the Overview and not of the class > documentation proper as usual? Good question. My take is that the typical *user* of the library is not generally immediately interested in the laws, and so I prefer to present the function synopses as quickly as possible up front. For the more sophisticated users who'll be implementing instances, the laws are are in their own section, with a link from the index at the top, an not buried in the middle of the topmatter. -- Viktor. From ben.franksen at online.de Sun Dec 27 10:35:23 2020 From: ben.franksen at online.de (Ben Franksen) Date: Sun, 27 Dec 2020 11:35:23 +0100 Subject: Improve documentation for Real In-Reply-To: References: Message-ID: Am 24.12.20 um 03:46 schrieb David Feuer: > Wouldn't it make more sense to get at the idea from another direction or > two? One obvious idea is to compare to a rational number: > > compareRational :: a -> Rational -> Ordering > > Neither this nor Ord can be supported by computable reals, Disclaimer: I have only a vague idea what computable reals are, which may explain why this is totally non-obvious to me! I mean, for Ord: yes, I do understand ahy this is not computable, but compareRational? Could you post a pointer or reference? Cheers Ben From ietf-dane at dukhovni.org Sun Dec 27 10:47:46 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 27 Dec 2020 05:47:46 -0500 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: <20201224212238.GO1459@straasha.imrryr.org> Message-ID: On Sun, Dec 27, 2020 at 05:31:31AM -0500, Viktor Dukhovni wrote: > > Otherwise: very well written. > > Thanks, while reworking it, some things gone mangled, and I haven't > finished the proofreading yet. I'll fix these pronto. Done. I'd be really great if someone were interested in stepping forward to take turns iterating on the document once or twice before we posting an MR on Gitlab. But if nobody has the cycles, or what I has is deemed close enogh as-is, then I'll just proof read some more and file an MR, probably before the year is out. With a bit of luck (for this MR), given the delay in GHC 9.0, perhaps it could even make it into the GHC 9.0 release. -- Viktor. From ietf-dane at dukhovni.org Sun Dec 27 10:55:12 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 27 Dec 2020 05:55:12 -0500 Subject: Improve documentation for Real In-Reply-To: References: Message-ID: On Sun, Dec 27, 2020 at 11:35:23AM +0100, Ben Franksen wrote: > Am 24.12.20 um 03:46 schrieb David Feuer: > > Wouldn't it make more sense to get at the idea from another direction or > > two? One obvious idea is to compare to a rational number: > > > > compareRational :: a -> Rational -> Ordering > > > > Neither this nor Ord can be supported by computable reals, > > Disclaimer: I have only a vague idea what computable reals are, which > may explain why this is totally non-obvious to me! > > I mean, for Ord: yes, I do understand ahy this is not computable, but > compareRational? Could you post a pointer or reference? There is no terminating algorithm that determines whether a computable real number that is (secretly) equal to zero is actually equal to zero. All you get to see is a sequence of approximations that make it look increasingly likely that the number could be zero, but there's no way to know that this is the case indefinitely and it is just very small. The equivalent situation with Foldable is the divergence of: all (== 0) $ repeat 0 the short-circuit never happens. So equality is not decidable, and the direction of strict inequality is only decidable for actually unequal numbers. -- Viktor. From ben.franksen at online.de Sun Dec 27 11:46:32 2020 From: ben.franksen at online.de (Ben Franksen) Date: Sun, 27 Dec 2020 12:46:32 +0100 Subject: Improve documentation for Real In-Reply-To: References: Message-ID: Am 27.12.20 um 11:55 schrieb Viktor Dukhovni: > On Sun, Dec 27, 2020 at 11:35:23AM +0100, Ben Franksen wrote: > >> Am 24.12.20 um 03:46 schrieb David Feuer: >>> Wouldn't it make more sense to get at the idea from another direction or >>> two? One obvious idea is to compare to a rational number: >>> >>> compareRational :: a -> Rational -> Ordering >>> >>> Neither this nor Ord can be supported by computable reals, >> >> Disclaimer: I have only a vague idea what computable reals are, which >> may explain why this is totally non-obvious to me! >> >> I mean, for Ord: yes, I do understand ahy this is not computable, but >> compareRational? Could you post a pointer or reference? > > There is no terminating algorithm that determines whether a computable > real number that is (secretly) equal to zero is actually equal to zero. > > All you get to see is a sequence of approximations that make it look > increasingly likely that the number could be zero, but there's no way > to know that this is the case indefinitely and it is just very small. > > The equivalent situation with Foldable is the divergence of: > > all (== 0) $ repeat 0 > > the short-circuit never happens. So equality is not decidable, and the > direction of strict inequality is only decidable for actually unequal > numbers. Thanks for this explanation. It is pretty obvious now! My inuition about computable reals was that they are something like (Integer,[Digit]) with an infinite sequence of decimals for the "fractional" part; and that when we compare with a rational, we /eventually/ come to a point where we can decide the comparison. But of course that is true only /if/ they are actually different; if they are equal, comparing the decimals won't terminate. Cheers Ben From oleg.grenrus at iki.fi Sun Dec 27 21:05:14 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Sun, 27 Dec 2020 23:05:14 +0200 Subject: type class Boolean In-Reply-To: References: <20201221101237.GD28742@cloudinit-builder> Message-ID: <0432bf82-f2f9-d22f-b4af-836bb0fe4e98@iki.fi> Wikipedia [1] has references > Bob Bemer added the \ character to the ASCII character set on September 18, 1961,[3][4] as the result of character frequency studies. In particular, the \ was introduced so that the ALGOL boolean operators ∧ (and) and ∨ (or) could be composed in ASCII as /\ and \/ respectively.[4][5] - Oleg [1] https://en.wikipedia.org/wiki/Backslash [3] http://www.thocp.net/biographies/bemer_bob.htm [4] https://web.archive.org/web/20130119163809/http://www.bobbemer.com/BACSLASH.HTM [5] https://web.archive.org/web/20090604210339/http://home.ccil.org/~remlaps/www.bobbemer.com/BRACES.HTM On 27.12.2020 12.03, Ben Franksen wrote: > Am 23.12.20 um 22:40 schrieb Jon Purdy: >> otherwise I like ‘(/\)’ and ‘(\/)’—which, after all, are the very >> reason the backslash was added to ASCII in the first place. > Interesting. Out of curiosity: do you have a reference for this? > > Cheers > Ben > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From ietf-dane at dukhovni.org Mon Dec 28 03:59:40 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Sun, 27 Dec 2020 22:59:40 -0500 Subject: Expanding Data.Foldable documentation with overview prose (pre-MR feedback requested) In-Reply-To: References: <20201224212238.GO1459@straasha.imrryr.org> Message-ID: On Sun, Dec 27, 2020 at 05:47:46AM -0500, Viktor Dukhovni wrote: > With a bit of luck (for this MR), given the delay in GHC 9.0, perhaps it > could even make it into the GHC 9.0 release. I went ahead and opened in MR: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/4689 -- Viktor. From ben.franksen at online.de Tue Dec 29 14:46:16 2020 From: ben.franksen at online.de (Ben Franksen) Date: Tue, 29 Dec 2020 15:46:16 +0100 Subject: type class Boolean In-Reply-To: <0432bf82-f2f9-d22f-b4af-836bb0fe4e98@iki.fi> References: <20201221101237.GD28742@cloudinit-builder> <0432bf82-f2f9-d22f-b4af-836bb0fe4e98@iki.fi> Message-ID: Thanks! Am 27.12.20 um 22:05 schrieb Oleg Grenrus: > Wikipedia [1] has references > >> Bob Bemer added the \ character to the ASCII character set on > September 18, 1961,[3][4] as the result of character frequency studies. > In particular, the \ was introduced so that the ALGOL boolean operators > ∧ (and) and ∨ (or) could be composed in ASCII as /\ and \/ > respectively.[4][5] > > - Oleg > > [1] https://en.wikipedia.org/wiki/Backslash > [3] http://www.thocp.net/biographies/bemer_bob.htm > [4] > https://web.archive.org/web/20130119163809/http://www.bobbemer.com/BACSLASH.HTM > [5] > https://web.archive.org/web/20090604210339/http://home.ccil.org/~remlaps/www.bobbemer.com/BRACES.HTM > > On 27.12.2020 12.03, Ben Franksen wrote: >> Am 23.12.20 um 22:40 schrieb Jon Purdy: >>> otherwise I like ‘(/\)’ and ‘(\/)’—which, after all, are the very >>> reason the backslash was added to ASCII in the first place. >> Interesting. Out of curiosity: do you have a reference for this? >> >> Cheers >> Ben >> >> _______________________________________________ >> 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 Wed Dec 30 18:32:16 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 30 Dec 2020 13:32:16 -0500 Subject: Proposal: Export Solo from Data.Tuple Message-ID: GHC.Tuple now exports data Solo a = Solo a for use as the canonical lifted unary tuple. I propose to export it from Data.Tuple. David From chessai1996 at gmail.com Wed Dec 30 18:57:27 2020 From: chessai1996 at gmail.com (chessai) Date: Wed, 30 Dec 2020 12:57:27 -0600 Subject: Proposal: Export Solo from Data.Tuple In-Reply-To: References: Message-ID: +1 On Wed, Dec 30, 2020, 12:32 David Feuer wrote: > GHC.Tuple now exports > > data Solo a = Solo a > > for use as the canonical lifted unary tuple. I propose to export it > from Data.Tuple. > > David > _______________________________________________ > 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 Wed Dec 30 19:23:20 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 30 Dec 2020 14:23:20 -0500 Subject: withFile defeats dead handle closure Message-ID: withFile keeps the handle it creates alive until the user action completes. If we want to avoid this, we can. All that's required is to capture the weak reference that holds the handle's finalizer. Then instead of closing the handle in the end (or on exception) using hClose, withFile can run the handle's finalizer. Should we do this? Or does it run too much against the idea that handles should be managed as explicitly as possible? -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg.grenrus at iki.fi Wed Dec 30 19:49:43 2020 From: oleg.grenrus at iki.fi (Oleg Grenrus) Date: Wed, 30 Dec 2020 21:49:43 +0200 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: I would be afraid of making this change. File descriptors are a scarce resource, and relying on non-deterministic GC behavior to free them is big -1. Also finalizers are not free in current GC. (Though, you probably cannot won't that many open files that it would matter). - Oleg On 30.12.2020 21.23, David Feuer wrote: > withFile keeps the handle it creates alive until the user action > completes. If we want to avoid this, we can. All that's required is to > capture the weak reference that holds the handle's finalizer. Then > instead of closing the handle in the end (or on exception) using > hClose, withFile can run the handle's finalizer. Should we do this? Or > does it run too much against the idea that handles should be managed > as explicitly as possible? > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From david.feuer at gmail.com Wed Dec 30 19:54:42 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 30 Dec 2020 14:54:42 -0500 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: Finalizers aren't free, but every handle already has a finalizer, so that's not an extra cost. On Wed, Dec 30, 2020, 2:50 PM Oleg Grenrus wrote: > I would be afraid of making this change. File descriptors are a scarce > resource, and relying on non-deterministic GC behavior to free them is > big -1. > > Also finalizers are not free in current GC. (Though, you probably cannot > won't that many open files that it would matter). > > - Oleg > > On 30.12.2020 21.23, David Feuer wrote: > > withFile keeps the handle it creates alive until the user action > > completes. If we want to avoid this, we can. All that's required is to > > capture the weak reference that holds the handle's finalizer. Then > > instead of closing the handle in the end (or on exception) using > > hClose, withFile can run the handle's finalizer. Should we do this? Or > > does it run too much against the idea that handles should be managed > > as explicitly as possible? > > > > _______________________________________________ > > 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 Wed Dec 30 20:47:50 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Wed, 30 Dec 2020 21:47:50 +0100 (CET) Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: On Wed, 30 Dec 2020, David Feuer wrote: > withFile keeps the handle it creates alive until the user action > completes. If we want to avoid this, we can. Why should we? From ryan at trinkle.org Wed Dec 30 20:55:40 2020 From: ryan at trinkle.org (Ryan Trinkle) Date: Wed, 30 Dec 2020 15:55:40 -0500 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: Although it might be nice to have a weak-reference-based alternative to withFile, I think it would be best to keep the behavior of withFile as predictable as possible (i.e. the current behavior), since closing a file can be semantically significant.  For instance, if someone is using /dev/watchdog to make their system automatically reboot when their userspace daemon fails, closing the file handle early would cause the watchdog functionality to be disabled, which is almost certainly not what someone would mean by `withFile "/dev/watchdog" $ \_ -> blah`. On 12/30/20 3:47 PM, Henning Thielemann wrote: > > On Wed, 30 Dec 2020, David Feuer wrote: > >> withFile keeps the handle it creates alive until the user action >> completes. If we want to avoid this, we can. > > Why should we? > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From lemming at henning-thielemann.de Wed Dec 30 21:05:29 2020 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Wed, 30 Dec 2020 22:05:29 +0100 (CET) Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: On Wed, 30 Dec 2020, Ryan Trinkle via Libraries wrote: > Although it might be nice to have a weak-reference-based alternative to > withFile, I think it would be best to keep the behavior of withFile as > predictable as possible (i.e. the current behavior), since closing a > file can be semantically significant. Right, if I open and close and re-open a file, it must be closed before I can re-open it. From ryan at trinkle.org Wed Dec 30 21:18:11 2020 From: ryan at trinkle.org (Ryan Trinkle) Date: Wed, 30 Dec 2020 16:18:11 -0500 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: <3d12f463-97b8-1ff9-af9e-695e6395e723@trinkle.org> I think David's suggestion may have been that withFile would still close the file at the end of the block, but would *also* close it if the handle died. On 12/30/20 4:05 PM, Henning Thielemann wrote: > > On Wed, 30 Dec 2020, Ryan Trinkle via Libraries wrote: > >> Although it might be nice to have a weak-reference-based alternative to >> withFile, I think it would be best to keep the behavior of withFile as >> predictable as possible (i.e. the current behavior), since closing a >> file can be semantically significant. > > Right, if I open and close and re-open a file, it must be closed > before I can re-open it. From ollie at ocharles.org.uk Wed Dec 30 21:25:56 2020 From: ollie at ocharles.org.uk (Oliver Charles) Date: Wed, 30 Dec 2020 21:25:56 +0000 Subject: withFile defeats dead handle closure In-Reply-To: <3d12f463-97b8-1ff9-af9e-695e6395e723@trinkle.org> References: <3d12f463-97b8-1ff9-af9e-695e6395e723@trinkle.org> Message-ID: <9521bd5c-88da-4380-8a05-259e4a29b9e1@www.fastmail.com> While maybe not directly related to this, for many small changes suggested to base the answer is often: go write a library and see how it works out. This is often for fairly stylistic changes to "fringe" components of base. Here we're talking about a full blown operational change to something incredibly common. If anything, I think it would have to subject to the same process - try it out, really use it anger, see what breaks and - hopefully! - what gets better. On Wed, 30 Dec 2020, at 9:18 PM, Ryan Trinkle via Libraries wrote: > I think David's suggestion may have been that withFile would still close > the file at the end of the block, but would *also* close it if the > handle died. > > On 12/30/20 4:05 PM, Henning Thielemann wrote: > > > > On Wed, 30 Dec 2020, Ryan Trinkle via Libraries wrote: > > > >> Although it might be nice to have a weak-reference-based alternative to > >> withFile, I think it would be best to keep the behavior of withFile as > >> predictable as possible (i.e. the current behavior), since closing a > >> file can be semantically significant. > > > > Right, if I open and close and re-open a file, it must be closed > > before I can re-open it. > _______________________________________________ > 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 Wed Dec 30 21:29:05 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 30 Dec 2020 16:29:05 -0500 Subject: withFile defeats dead handle closure In-Reply-To: <9521bd5c-88da-4380-8a05-259e4a29b9e1@www.fastmail.com> References: <3d12f463-97b8-1ff9-af9e-695e6395e723@trinkle.org> <9521bd5c-88da-4380-8a05-259e4a29b9e1@www.fastmail.com> Message-ID: To be clear, I wasn't formally proposing a change. I was trying to get a sense of what people thought of the notion before going down too many rabbit holes. I think Ryan Trinkle's concern is quite strong enough to kill this idea as a change to `withFile` itself. On Wed, Dec 30, 2020 at 4:26 PM Oliver Charles wrote: > > While maybe not directly related to this, for many small changes suggested to base the answer is often: go write a library and see how it works out. This is often for fairly stylistic changes to "fringe" components of base. Here we're talking about a full blown operational change to something incredibly common. If anything, I think it would have to subject to the same process - try it out, really use it anger, see what breaks and - hopefully! - what gets better. > > On Wed, 30 Dec 2020, at 9:18 PM, Ryan Trinkle via Libraries wrote: > > I think David's suggestion may have been that withFile would still close > the file at the end of the block, but would *also* close it if the > handle died. > > On 12/30/20 4:05 PM, Henning Thielemann wrote: > > > > On Wed, 30 Dec 2020, Ryan Trinkle via Libraries wrote: > > > >> Although it might be nice to have a weak-reference-based alternative to > >> withFile, I think it would be best to keep the behavior of withFile as > >> predictable as possible (i.e. the current behavior), since closing a > >> file can be semantically significant. > > > > Right, if I open and close and re-open a file, it must be closed > > before I can re-open it. > _______________________________________________ > 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 ietf-dane at dukhovni.org Wed Dec 30 21:32:40 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Wed, 30 Dec 2020 16:32:40 -0500 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: On Wed, Dec 30, 2020 at 02:23:20PM -0500, David Feuer wrote: > withFile keeps the handle it creates alive until the user action completes. > If we want to avoid this, we can. All that's required is to capture the > weak reference that holds the handle's finalizer. Then instead of closing > the handle in the end (or on exception) using hClose, withFile can run the > handle's finalizer. Should we do this? Or does it run too much against the > idea that handles should be managed as explicitly as possible? I'm not sure what you mean by "keeps alive", it passes the handle to the action, and closes it when the action returns, but the action, can (if it so chooses) also close the handle in a more timely manner, because "hClose" is idempotent. So it does not seem like any change is needed here... Am I missing something? The below compiles and runs, with no errors: module Main (main) where import System.IO main :: IO () main = do withFile "/etc/passwd" ReadMode $ \f -> hClose f >> hClose f withFile "/etc/passwd" ReadMode $ \f -> hClose f >> hClose f -- Viktor. From david.feuer at gmail.com Wed Dec 30 21:39:52 2020 From: david.feuer at gmail.com (David Feuer) Date: Wed, 30 Dec 2020 16:39:52 -0500 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: The handle will not be closed early if it becomes unreachable within the user action (without the user closing it). It sounds like the consensus is that that's how it should be, so I'll leave that well enough alone. On Wed, Dec 30, 2020 at 4:32 PM Viktor Dukhovni wrote: > > On Wed, Dec 30, 2020 at 02:23:20PM -0500, David Feuer wrote: > > > withFile keeps the handle it creates alive until the user action completes. > > If we want to avoid this, we can. All that's required is to capture the > > weak reference that holds the handle's finalizer. Then instead of closing > > the handle in the end (or on exception) using hClose, withFile can run the > > handle's finalizer. Should we do this? Or does it run too much against the > > idea that handles should be managed as explicitly as possible? > > I'm not sure what you mean by "keeps alive", it passes the handle to the > action, and closes it when the action returns, but the action, can (if > it so chooses) also close the handle in a more timely manner, because > "hClose" is idempotent. So it does not seem like any change is needed > here... Am I missing something? > > The below compiles and runs, with no errors: > > module Main (main) where > import System.IO > > main :: IO () > main = do > withFile "/etc/passwd" ReadMode $ \f -> hClose f >> hClose f > withFile "/etc/passwd" ReadMode $ \f -> hClose f >> hClose f > > -- > Viktor. > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From ietf-dane at dukhovni.org Wed Dec 30 21:46:45 2020 From: ietf-dane at dukhovni.org (Viktor Dukhovni) Date: Wed, 30 Dec 2020 16:46:45 -0500 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: On Wed, Dec 30, 2020 at 04:39:52PM -0500, David Feuer wrote: > The handle will not be closed early if it becomes unreachable within > the user action (without the user closing it). It sounds like the > consensus is that that's how it should be, so I'll leave that well > enough alone. I see, the converse of what I guessed you were saying. I agree this is not worth changing. It would amount to relying on GC to close the handle perhaps a bit earlier, and my take is that any such reliance is a bug. If the action keeps executing long after the file is no longer needed then the programmer used "withFile" in too broad a context and needs to narrow its scope to just the portion of the code that is actually using the file. -- Viktor. From svenpanne at gmail.com Thu Dec 31 10:26:09 2020 From: svenpanne at gmail.com (Sven Panne) Date: Thu, 31 Dec 2020 11:26:09 +0100 Subject: withFile defeats dead handle closure In-Reply-To: References: Message-ID: Am Mi., 30. Dez. 2020 um 22:47 Uhr schrieb Viktor Dukhovni < ietf-dane at dukhovni.org>: > [...] It would amount to relying on GC to close the handle perhaps a bit > earlier, and my take is that any such reliance is a bug.[...] +1 As a general rule of thumb: Automatic memory management is good for, well, memory management, but nothing else. Quite the opposite: Most of the time it's horrible for other tasks. There are tons of points in the design space of automatic memory management with vastly different trade-offs regarding throughput, latency, concurrency etc., so tying other "heavy" resources like file descriptors to automatic memory management is a very, very bad idea. People had cunning ideas about how to (ab-)use finalizers etc. for decades, but basically all of them turned out to be bad. Hans-J. Boehm has written extensively about this, and his papers are still worth reading today. -------------- next part -------------- An HTML attachment was scrubbed... URL: