From andrew.thaddeus at gmail.com Wed Dec 6 14:28:37 2017 From: andrew.thaddeus at gmail.com (Andrew Martin) Date: Wed, 6 Dec 2017 09:28:37 -0500 Subject: Add foldMapM to Data.Foldable Message-ID: Several coworkers and myself have independently reinvented this function several times: foldMapM :: (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> m b foldMapM f xs = foldlM (\b a -> mappend b <$> (f a)) mempty xs I would like to propose that this be added to Data.Foldable. We have the triplet foldr,foldl,foldMap in the Foldable typeclass itself, and Data.Foldable provides foldrM and foldlM. It would be nice to provide foldMapM for symmetry and because it seems to be useful in a variety of applications. -- -Andrew Thaddeus Martin -------------- next part -------------- An HTML attachment was scrubbed... URL: From andreas.abel at ifi.lmu.de Wed Dec 6 23:04:02 2017 From: andreas.abel at ifi.lmu.de (Andreas Abel) Date: Thu, 7 Dec 2017 00:04:02 +0100 Subject: Add foldMapM to Data.Foldable In-Reply-To: References: Message-ID: +1. If I remember correctly, then Henning Thielemann has suggested this as the proper generalization of mapM_. On 06.12.2017 15:28, Andrew Martin wrote: > Several coworkers and myself have independently reinvented this function > several times: > >     foldMapM :: (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> m b >     foldMapM f xs = foldlM (\b a -> mappend b <$> (f a)) mempty xs > > I would like to propose that this be added to Data.Foldable. We have the > triplet foldr,foldl,foldMap in the Foldable typeclass itself, and > Data.Foldable provides foldrM and foldlM. It would be nice to provide > foldMapM for symmetry and because it seems to be useful in a variety of > applications. > > -- > -Andrew Thaddeus Martin > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www.cse.chalmers.se/~abela/ From david.feuer at gmail.com Wed Dec 6 23:11:07 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 6 Dec 2017 18:11:07 -0500 Subject: Add foldMapM to Data.Foldable In-Reply-To: References: Message-ID: It seems this lazily-accumulating version should be Applicative, and a strict version Monad. Do we also need a right-to-left version of each? On Dec 6, 2017 9:29 AM, "Andrew Martin" wrote: Several coworkers and myself have independently reinvented this function several times: foldMapM :: (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> m b foldMapM f xs = foldlM (\b a -> mappend b <$> (f a)) mempty xs I would like to propose that this be added to Data.Foldable. We have the triplet foldr,foldl,foldMap in the Foldable typeclass itself, and Data.Foldable provides foldrM and foldlM. It would be nice to provide foldMapM for symmetry and because it seems to be useful in a variety of applications. -- -Andrew Thaddeus Martin _______________________________________________ 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 andrew.thaddeus at gmail.com Thu Dec 7 00:27:43 2017 From: andrew.thaddeus at gmail.com (Andrew Martin) Date: Wed, 6 Dec 2017 19:27:43 -0500 Subject: Add foldMapM to Data.Foldable In-Reply-To: References: Message-ID: I had not considered that. I tried it out on a gist ( https://gist.github.com/andrewthad/25d1d443ec54412ae96cea3f40411e45), and you're definitely right. I don't understand right monadic folds well enough to write those out, but it would probably be worthwhile to both variants of it as well. Here's the code from the gist: {-# LANGUAGE ScopedTypeVariables #-} module Folds where import Control.Applicative -- Lazy in the monoidal accumulator. foldlMapM :: forall g b a m. (Foldable g, Monoid b, Applicative m) => (a -> m b) -> g a -> m b foldlMapM f = foldr f' (pure mempty) where f' :: a -> m b -> m b f' x y = liftA2 mappend (f x) y -- Strict in the monoidal accumulator. For monads strict -- in the left argument of bind, this will run in constant -- space. foldlMapM' :: forall g b a m. (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> m b foldlMapM' f xs = foldr f' pure xs mempty where f' :: a -> (b -> m b) -> b -> m b f' x k bl = do br <- f x let !b = mappend bl br k b On Wed, Dec 6, 2017 at 6:11 PM, David Feuer wrote: > It seems this lazily-accumulating version should be Applicative, and a > strict version Monad. Do we also need a right-to-left version of each? > > On Dec 6, 2017 9:29 AM, "Andrew Martin" wrote: > > Several coworkers and myself have independently reinvented this function > several times: > > foldMapM :: (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> m b > foldMapM f xs = foldlM (\b a -> mappend b <$> (f a)) mempty xs > > I would like to propose that this be added to Data.Foldable. We have the > triplet foldr,foldl,foldMap in the Foldable typeclass itself, and > Data.Foldable provides foldrM and foldlM. It would be nice to provide > foldMapM for symmetry and because it seems to be useful in a variety of > applications. > > -- > -Andrew Thaddeus Martin > > _______________________________________________ > 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 david.feuer at gmail.com Thu Dec 7 01:20:32 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 6 Dec 2017 20:20:32 -0500 Subject: Add foldMapM to Data.Foldable In-Reply-To: References: Message-ID: Actually, the most "natural" Applicative version is probably this: newtype Ap f a = Ap {getAp :: f a} instance (Applicative f, Monoid a) => Monoid (Ap f a) where mempty = Ap $ pure mempty mappend (Ap x) (Ap y) = Ap $ liftA2 mappend x y foldMapA :: (Foldable t, Monoid m, Applicative f) => (a -> f m) -> t a -> f m foldMapA f = getAp . foldMap (Ap . f) Of course, we can use some Data.Coerce magic to avoid silly eta expansion, as usual. The "right" way to perform the actions in the opposite order is probably just foldMapA f . Reverse and you can accumulate the other way using getDual . foldMapA (Dual . f) So I think the whole Applicative side of this proposal might be seen as further motivation for my long-ago stalled proposal to add Ap to Data.Monoid. On Wed, Dec 6, 2017 at 7:27 PM, Andrew Martin wrote: > I had not considered that. I tried it out on a gist > (https://gist.github.com/andrewthad/25d1d443ec54412ae96cea3f40411e45), and > you're definitely right. I don't understand right monadic folds well enough > to write those out, but it would probably be worthwhile to both variants of > it as well. Here's the code from the gist: > > {-# LANGUAGE ScopedTypeVariables #-} > > module Folds where > > import Control.Applicative > > -- Lazy in the monoidal accumulator. > foldlMapM :: forall g b a m. (Foldable g, Monoid b, Applicative m) => (a -> > m b) -> g a -> m b > foldlMapM f = foldr f' (pure mempty) > where > f' :: a -> m b -> m b > f' x y = liftA2 mappend (f x) y > > -- Strict in the monoidal accumulator. For monads strict > -- in the left argument of bind, this will run in constant > -- space. > foldlMapM' :: forall g b a m. (Foldable g, Monoid b, Monad m) => (a -> m b) > -> g a -> m b > foldlMapM' f xs = foldr f' pure xs mempty > where > f' :: a -> (b -> m b) -> b -> m b > f' x k bl = do > br <- f x > let !b = mappend bl br > k b > > > On Wed, Dec 6, 2017 at 6:11 PM, David Feuer wrote: >> >> It seems this lazily-accumulating version should be Applicative, and a >> strict version Monad. Do we also need a right-to-left version of each? >> >> On Dec 6, 2017 9:29 AM, "Andrew Martin" wrote: >> >> Several coworkers and myself have independently reinvented this function >> several times: >> >> foldMapM :: (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> m >> b >> foldMapM f xs = foldlM (\b a -> mappend b <$> (f a)) mempty xs >> >> I would like to propose that this be added to Data.Foldable. We have the >> triplet foldr,foldl,foldMap in the Foldable typeclass itself, and >> Data.Foldable provides foldrM and foldlM. It would be nice to provide >> foldMapM for symmetry and because it seems to be useful in a variety of >> applications. >> >> -- >> -Andrew Thaddeus Martin >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> > > > > -- > -Andrew Thaddeus Martin From david.feuer at gmail.com Thu Dec 7 04:15:44 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 6 Dec 2017 23:15:44 -0500 Subject: Add foldMapM to Data.Foldable In-Reply-To: References: Message-ID: Actually, the key modifiers are probably Dual and Backwards, with Reverse combining them. Or something like that. On Dec 6, 2017 8:20 PM, "David Feuer" wrote: > Actually, the most "natural" Applicative version is probably this: > > newtype Ap f a = Ap {getAp :: f a} > instance (Applicative f, Monoid a) => Monoid (Ap f a) where > mempty = Ap $ pure mempty > mappend (Ap x) (Ap y) = Ap $ liftA2 mappend x y > > foldMapA :: (Foldable t, Monoid m, Applicative f) => (a -> f m) -> t a -> > f m > foldMapA f = getAp . foldMap (Ap . f) > > Of course, we can use some Data.Coerce magic to avoid silly eta > expansion, as usual. > > The "right" way to perform the actions in the opposite order is probably > just > > foldMapA f . Reverse > > and you can accumulate the other way using getDual . foldMapA (Dual . f) > > So I think the whole Applicative side of this proposal might be seen as > further > motivation for my long-ago stalled proposal to add Ap to Data.Monoid. > > On Wed, Dec 6, 2017 at 7:27 PM, Andrew Martin > wrote: > > I had not considered that. I tried it out on a gist > > (https://gist.github.com/andrewthad/25d1d443ec54412ae96cea3f40411e45), > and > > you're definitely right. I don't understand right monadic folds well > enough > > to write those out, but it would probably be worthwhile to both variants > of > > it as well. Here's the code from the gist: > > > > {-# LANGUAGE ScopedTypeVariables #-} > > > > module Folds where > > > > import Control.Applicative > > > > -- Lazy in the monoidal accumulator. > > foldlMapM :: forall g b a m. (Foldable g, Monoid b, Applicative m) => (a > -> > > m b) -> g a -> m b > > foldlMapM f = foldr f' (pure mempty) > > where > > f' :: a -> m b -> m b > > f' x y = liftA2 mappend (f x) y > > > > -- Strict in the monoidal accumulator. For monads strict > > -- in the left argument of bind, this will run in constant > > -- space. > > foldlMapM' :: forall g b a m. (Foldable g, Monoid b, Monad m) => (a -> m > b) > > -> g a -> m b > > foldlMapM' f xs = foldr f' pure xs mempty > > where > > f' :: a -> (b -> m b) -> b -> m b > > f' x k bl = do > > br <- f x > > let !b = mappend bl br > > k b > > > > > > On Wed, Dec 6, 2017 at 6:11 PM, David Feuer > wrote: > >> > >> It seems this lazily-accumulating version should be Applicative, and a > >> strict version Monad. Do we also need a right-to-left version of each? > >> > >> On Dec 6, 2017 9:29 AM, "Andrew Martin" > wrote: > >> > >> Several coworkers and myself have independently reinvented this function > >> several times: > >> > >> foldMapM :: (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> > m > >> b > >> foldMapM f xs = foldlM (\b a -> mappend b <$> (f a)) mempty xs > >> > >> I would like to propose that this be added to Data.Foldable. We have the > >> triplet foldr,foldl,foldMap in the Foldable typeclass itself, and > >> Data.Foldable provides foldrM and foldlM. It would be nice to provide > >> foldMapM for symmetry and because it seems to be useful in a variety of > >> applications. > >> > >> -- > >> -Andrew Thaddeus Martin > >> > >> _______________________________________________ > >> 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 david.feuer at gmail.com Thu Dec 7 21:04:18 2017 From: david.feuer at gmail.com (David Feuer) Date: Thu, 7 Dec 2017 16:04:18 -0500 Subject: Add foldMapM to Data.Foldable In-Reply-To: References: Message-ID: Indeed, f g = g (\x -> putStr x >> pure x) ["hi", "I'm", "Bob"] f foldMapA = f $ \g -> getAp . foldMap (Ap . g) prints "hiI'mBob" and returns "hiI'mBob" f (\g -> forwards . foldMayO (Backwards . g)) = f (\g -> forwards . getAp . foldMap (Ap . Backwards . g)) prints "BobI'mhi" and returns "hiI'mBob" f (\g -> fmap getDual . foldMapA (fmap Dual . g)) = f (\g -> fmap getDual . foldMap (Ap . fmap Dual . g)) prints "hiI'mBob" and returns "BobI'mHi" f (\g -> foldMapA g . Reverse) = f (\g -> getAp . getDual . foldMap (Dual . Ap . g) prints "BobI'mHi" and returns "BobI'mHi" None of this affects the strict (monadic) versions, which should be defined in terms of foldr and foldl. It's not entirely clear to me which way those monadic versions should accumulate. On Wed, Dec 6, 2017 at 11:15 PM, David Feuer wrote: > Actually, the key modifiers are probably Dual and Backwards, with Reverse > combining them. Or something like that. > > On Dec 6, 2017 8:20 PM, "David Feuer" wrote: >> >> Actually, the most "natural" Applicative version is probably this: >> >> newtype Ap f a = Ap {getAp :: f a} >> instance (Applicative f, Monoid a) => Monoid (Ap f a) where >> mempty = Ap $ pure mempty >> mappend (Ap x) (Ap y) = Ap $ liftA2 mappend x y >> >> foldMapA :: (Foldable t, Monoid m, Applicative f) => (a -> f m) -> t a -> >> f m >> foldMapA f = getAp . foldMap (Ap . f) >> >> Of course, we can use some Data.Coerce magic to avoid silly eta >> expansion, as usual. >> >> The "right" way to perform the actions in the opposite order is probably >> just >> >> foldMapA f . Reverse >> >> and you can accumulate the other way using getDual . foldMapA (Dual . f) >> >> So I think the whole Applicative side of this proposal might be seen as >> further >> motivation for my long-ago stalled proposal to add Ap to Data.Monoid. >> >> On Wed, Dec 6, 2017 at 7:27 PM, Andrew Martin >> wrote: >> > I had not considered that. I tried it out on a gist >> > (https://gist.github.com/andrewthad/25d1d443ec54412ae96cea3f40411e45), >> > and >> > you're definitely right. I don't understand right monadic folds well >> > enough >> > to write those out, but it would probably be worthwhile to both variants >> > of >> > it as well. Here's the code from the gist: >> > >> > {-# LANGUAGE ScopedTypeVariables #-} >> > >> > module Folds where >> > >> > import Control.Applicative >> > >> > -- Lazy in the monoidal accumulator. >> > foldlMapM :: forall g b a m. (Foldable g, Monoid b, Applicative m) => (a >> > -> >> > m b) -> g a -> m b >> > foldlMapM f = foldr f' (pure mempty) >> > where >> > f' :: a -> m b -> m b >> > f' x y = liftA2 mappend (f x) y >> > >> > -- Strict in the monoidal accumulator. For monads strict >> > -- in the left argument of bind, this will run in constant >> > -- space. >> > foldlMapM' :: forall g b a m. (Foldable g, Monoid b, Monad m) => (a -> m >> > b) >> > -> g a -> m b >> > foldlMapM' f xs = foldr f' pure xs mempty >> > where >> > f' :: a -> (b -> m b) -> b -> m b >> > f' x k bl = do >> > br <- f x >> > let !b = mappend bl br >> > k b >> > >> > >> > On Wed, Dec 6, 2017 at 6:11 PM, David Feuer >> > wrote: >> >> >> >> It seems this lazily-accumulating version should be Applicative, and a >> >> strict version Monad. Do we also need a right-to-left version of each? >> >> >> >> On Dec 6, 2017 9:29 AM, "Andrew Martin" >> >> wrote: >> >> >> >> Several coworkers and myself have independently reinvented this >> >> function >> >> several times: >> >> >> >> foldMapM :: (Foldable g, Monoid b, Monad m) => (a -> m b) -> g a -> >> >> m >> >> b >> >> foldMapM f xs = foldlM (\b a -> mappend b <$> (f a)) mempty xs >> >> >> >> I would like to propose that this be added to Data.Foldable. We have >> >> the >> >> triplet foldr,foldl,foldMap in the Foldable typeclass itself, and >> >> Data.Foldable provides foldrM and foldlM. It would be nice to provide >> >> foldMapM for symmetry and because it seems to be useful in a variety of >> >> applications. >> >> >> >> -- >> >> -Andrew Thaddeus Martin >> >> >> >> _______________________________________________ >> >> Libraries mailing list >> >> Libraries at haskell.org >> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> >> >> >> > >> > >> > >> > -- >> > -Andrew Thaddeus Martin From m at tweag.io Sat Dec 9 15:10:16 2017 From: m at tweag.io (Boespflug, Mathieu) Date: Sat, 9 Dec 2017 16:10:16 +0100 Subject: [Haskell-cafe] Maintenance of streaming and streaming-bytestring In-Reply-To: References: Message-ID: I'd like to contributed streaming-binary to the streaming GitHub org, if you're up for it. http://hackage.haskell.org/package/streaming-binary Best, -- Mathieu Boespflug Founder at http://tweag.io. On 17 September 2017 at 01:24, David Feuer wrote: > Ah, right. Then yes, that sounds like a great approach. > > On Sep 15, 2017 1:23 PM, "Carter Schonwald" > wrote: > >> GitHub has a transfer repo ownership toggle you can do to move the main >> repo and it's assets >> >> On Fri, Sep 15, 2017 at 1:05 PM David Feuer >> wrote: >> >>> Having an organization (with multiple owners and members) makes for much >>> smoother transitions when maintainers change. That goes triple for >>> unexpected changes. There's (still!) no really good way to migrate an issue >>> tracker or PRs from one repository to another. Unfortunately, for that same >>> reason, I believe that actually moving your project to the organization >>> will be quite unpleasant if there are more than a few open tickets. And if >>> there are more than a few closed tickets, then preserving history in a >>> useful history seems hard too. Maybe someone else knows a reason this isn't >>> actually terrible. >>> >>> David >>> >>> On Sep 14, 2017 1:10 AM, "Ivan Lazar Miljenovic" < >>> ivan.miljenovic at gmail.com> wrote: >>> >>> Since you've seem to set this up as an organisation, would you be >>> interested in my moving over the various streaming libraries I have >>> there as well? >>> >>> On 14 September 2017 at 03:31, Andrew Martin >>> wrote: >>> > The streaming and streaming-bytestring libraries are now being >>> maintained >>> > here: https://github.com/haskell-streaming >>> > >>> > On Tue, Sep 12, 2017 at 4:50 PM, Andrew Martin < >>> andrew.thaddeus at gmail.com> >>> > wrote: >>> >> >>> >> Thanks adding me as a maintainer. I'm new to this process, so I >>> appreciate >>> >> the tip about admin at hackage.haskell.org as well. >>> >> >>> >> -Andrew Martin >>> >> >>> >> On Tue, Sep 12, 2017 at 3:57 PM, Erik Hesselink >>> >> wrote: >>> >>> >>> >>> Hi Andrew, >>> >>> >>> >>> We usually allow about 3 weeks for the maintainer to respond. Since >>> that >>> >>> time has now passed I've added you as a maintainer for streaming and >>> >>> streaming-bytestring. Let me know if there's anything else you need. >>> >>> >>> >>> For others looking to take over a package in the future, please CC >>> >>> admin at hackage.haskell.org, there's a higher chance I'll see it >>> there than >>> >>> just on the email lists. >>> >>> >>> >>> Regards, >>> >>> >>> >>> Erik (hackage admin) >>> >>> >>> >>> On 12 September 2017 at 20:18, Andrew Martin < >>> andrew.thaddeus at gmail.com> >>> >>> wrote: >>> >>>> >>> >>>> Are there any further steps that I can take? >>> >>>> >>> >>>> On Thu, Sep 7, 2017 at 11:07 AM, Andrew Martin >>> >>>> wrote: >>> >>>>> >>> >>>>> David Feuer brought this up two weeks ago [0]. The maintainer of >>> >>>>> streaming and streaming-bytestring has been unreachable, and >>> provided his >>> >>>>> continued absence, I would like to become a maintainer of these two >>> >>>>> libraries. I have put up PRs fixing issues [1] and I've offered on >>> the issue >>> >>>>> tracker to become a comaintainer [2]. I use this library a lot at >>> work, so I >>> >>>>> have an interest in keeping it in good shape. >>> >>>>> >>> >>>>> [0] >>> >>>>> https://mail.haskell.org/pipermail/libraries/2017-August/ >>> 028141.html >>> >>>>> [1] https://github.com/michaelt/streaming-bytestring/pull/11 >>> >>>>> [2] https://github.com/michaelt/streaming-bytestring/issues/19 >>> >>>>> >>> >>>>> -- >>> >>>>> -Andrew Thaddeus Martin >>> >>>> >>> >>>> >>> >>>> >>> >>>> >>> >>>> -- >>> >>>> -Andrew Thaddeus Martin >>> >>>> >>> >>>> _______________________________________________ >>> >>>> Libraries mailing list >>> >>>> Libraries at haskell.org >>> >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >>> >>>> >>> >>> >>> >> >>> >> >>> >> >>> >> -- >>> >> -Andrew Thaddeus Martin >>> > >>> > >>> > >>> > >>> > -- >>> > -Andrew Thaddeus Martin >>> > >>> > _______________________________________________ >>> > Haskell-Cafe mailing list >>> > To (un)subscribe, modify options or view archives go to: >>> > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>> > Only members subscribed via the mailman list are allowed to post. >>> >>> >>> >>> -- >>> Ivan Lazar Miljenovic >>> Ivan.Miljenovic at gmail.com >>> http://IvanMiljenovic.wordpress.com >>> _______________________________________________ >>> Haskell-Cafe mailing list >>> To (un)subscribe, modify options or view archives go to: >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>> Only members subscribed via the mailman list are allowed to post. >>> >>> >>> _______________________________________________ >>> Haskell-Cafe mailing list >>> To (un)subscribe, modify options or view archives go to: >>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>> Only members subscribed via the mailman list are allowed to post. >> >> > _______________________________________________ > 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 11 13:04:50 2017 From: david.feuer at gmail.com (David Feuer) Date: Mon, 11 Dec 2017 08:04:50 -0500 Subject: [Haskell-cafe] Maintenance of streaming and streaming-bytestring In-Reply-To: References: Message-ID: I've added you as a member of haskell-streaming. Feel free to transfer the repo. On Sat, Dec 9, 2017 at 10:10 AM, Boespflug, Mathieu wrote: > I'd like to contributed streaming-binary to the streaming GitHub org, if > you're up for it. > > http://hackage.haskell.org/package/streaming-binary > > Best, > > -- > Mathieu Boespflug > Founder at http://tweag.io. > > On 17 September 2017 at 01:24, David Feuer wrote: >> >> Ah, right. Then yes, that sounds like a great approach. >> >> On Sep 15, 2017 1:23 PM, "Carter Schonwald" >> wrote: >>> >>> GitHub has a transfer repo ownership toggle you can do to move the main >>> repo and it's assets >>> >>> On Fri, Sep 15, 2017 at 1:05 PM David Feuer >>> wrote: >>>> >>>> Having an organization (with multiple owners and members) makes for much >>>> smoother transitions when maintainers change. That goes triple for >>>> unexpected changes. There's (still!) no really good way to migrate an issue >>>> tracker or PRs from one repository to another. Unfortunately, for that same >>>> reason, I believe that actually moving your project to the organization will >>>> be quite unpleasant if there are more than a few open tickets. And if there >>>> are more than a few closed tickets, then preserving history in a useful >>>> history seems hard too. Maybe someone else knows a reason this isn't >>>> actually terrible. >>>> >>>> David >>>> >>>> On Sep 14, 2017 1:10 AM, "Ivan Lazar Miljenovic" >>>> wrote: >>>> >>>> Since you've seem to set this up as an organisation, would you be >>>> interested in my moving over the various streaming libraries I have >>>> there as well? >>>> >>>> On 14 September 2017 at 03:31, Andrew Martin >>>> wrote: >>>> > The streaming and streaming-bytestring libraries are now being >>>> > maintained >>>> > here: https://github.com/haskell-streaming >>>> > >>>> > On Tue, Sep 12, 2017 at 4:50 PM, Andrew Martin >>>> > >>>> > wrote: >>>> >> >>>> >> Thanks adding me as a maintainer. I'm new to this process, so I >>>> >> appreciate >>>> >> the tip about admin at hackage.haskell.org as well. >>>> >> >>>> >> -Andrew Martin >>>> >> >>>> >> On Tue, Sep 12, 2017 at 3:57 PM, Erik Hesselink >>>> >> wrote: >>>> >>> >>>> >>> Hi Andrew, >>>> >>> >>>> >>> We usually allow about 3 weeks for the maintainer to respond. Since >>>> >>> that >>>> >>> time has now passed I've added you as a maintainer for streaming and >>>> >>> streaming-bytestring. Let me know if there's anything else you need. >>>> >>> >>>> >>> For others looking to take over a package in the future, please CC >>>> >>> admin at hackage.haskell.org, there's a higher chance I'll see it there >>>> >>> than >>>> >>> just on the email lists. >>>> >>> >>>> >>> Regards, >>>> >>> >>>> >>> Erik (hackage admin) >>>> >>> >>>> >>> On 12 September 2017 at 20:18, Andrew Martin >>>> >>> >>>> >>> wrote: >>>> >>>> >>>> >>>> Are there any further steps that I can take? >>>> >>>> >>>> >>>> On Thu, Sep 7, 2017 at 11:07 AM, Andrew Martin >>>> >>>> wrote: >>>> >>>>> >>>> >>>>> David Feuer brought this up two weeks ago [0]. The maintainer of >>>> >>>>> streaming and streaming-bytestring has been unreachable, and >>>> >>>>> provided his >>>> >>>>> continued absence, I would like to become a maintainer of these >>>> >>>>> two >>>> >>>>> libraries. I have put up PRs fixing issues [1] and I've offered on >>>> >>>>> the issue >>>> >>>>> tracker to become a comaintainer [2]. I use this library a lot at >>>> >>>>> work, so I >>>> >>>>> have an interest in keeping it in good shape. >>>> >>>>> >>>> >>>>> [0] >>>> >>>>> >>>> >>>>> https://mail.haskell.org/pipermail/libraries/2017-August/028141.html >>>> >>>>> [1] https://github.com/michaelt/streaming-bytestring/pull/11 >>>> >>>>> [2] https://github.com/michaelt/streaming-bytestring/issues/19 >>>> >>>>> >>>> >>>>> -- >>>> >>>>> -Andrew Thaddeus Martin >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> -- >>>> >>>> -Andrew Thaddeus Martin >>>> >>>> >>>> >>>> _______________________________________________ >>>> >>>> Libraries mailing list >>>> >>>> Libraries at haskell.org >>>> >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >>>> >>>> >>>> >>> >>>> >> >>>> >> >>>> >> >>>> >> -- >>>> >> -Andrew Thaddeus Martin >>>> > >>>> > >>>> > >>>> > >>>> > -- >>>> > -Andrew Thaddeus Martin >>>> > >>>> > _______________________________________________ >>>> > Haskell-Cafe mailing list >>>> > To (un)subscribe, modify options or view archives go to: >>>> > http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>>> > Only members subscribed via the mailman list are allowed to post. >>>> >>>> >>>> >>>> -- >>>> Ivan Lazar Miljenovic >>>> Ivan.Miljenovic at gmail.com >>>> http://IvanMiljenovic.wordpress.com >>>> _______________________________________________ >>>> Haskell-Cafe mailing list >>>> To (un)subscribe, modify options or view archives go to: >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>>> Only members subscribed via the mailman list are allowed to post. >>>> >>>> >>>> _______________________________________________ >>>> Haskell-Cafe mailing list >>>> To (un)subscribe, modify options or view archives go to: >>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe >>>> Only members subscribed via the mailman list are allowed to post. >> >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> > From strake888 at gmail.com Thu Dec 14 03:48:10 2017 From: strake888 at gmail.com (M Farkas-Dyck) Date: Wed, 13 Dec 2017 19:48:10 -0800 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` Message-ID: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> I propose to add the following methods to `Bits` and `FiniteBits` classes: class Bits a where ... bitSizeMaybe' :: Proxy a -> Maybe Int class FiniteBits b where ... finiteBitSize' :: Proxy b -> Int Rationale: working with an arbitrary `Bits a => a`, one may not have a value of type `a` as argument to `bitSizeMaybe` or `finiteBitSize`, and writing `undefined` makes me feel dirty. From strake888 at gmail.com Thu Dec 14 04:11:03 2017 From: strake888 at gmail.com (M Farkas-Dyck) Date: Wed, 13 Dec 2017 20:11:03 -0800 Subject: Proposal: `Enum` class overhaul Message-ID: I propose to add some new methods of `Enum`: class Enum a where ... predMay, succMay :: a -> Maybe a toEnum' :: Integer -> Maybe a fromEnum' a -> Integer Rationale for `fromEnum'` and `toEnum'`: The docs for `Enum` now say the minimal complete definition is `toEnum` and `fromEnum`, but this is not enough to have sane default instances of the other methods, for example: data ABC = A | B | C deriving Show instance Enum ABC where toEnum 0 = A toEnum 1 = B toEnum 2 = C fromEnum A = 0 fromEnum B = 1 fromEnum C = 2 main = print [A ..] -- [A,B,C,*** Exception: Non-exhaustive patterns in function toEnum In this case one could merely derive `Enum`, but not in some other cases, e.g. numeric types or GADTs. It is not possible to do better defining `toEnum` and `fromEnum` alone. If we default-define `toEnum'` and `fromEnum'` and their evil (i.e. partial) syblings in terms of each other, the user need merely define the total methods. Using `Integer` rather than `Int` allows these methods to not fail for types larger than an `Int`, which are not uncommon on 32-bit systems. Rationale for `predMay` and `succMay`: I include these partly for completeness, but `predMay` can not now be defined in general, and `succMay` only cumbersomely in terms of `enumFrom`. Note: All rationales imply "unless one uses `unsafePerformIO`". I'd rather not, myself. From david.feuer at gmail.com Thu Dec 14 04:19:47 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 13 Dec 2017 23:19:47 -0500 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: +1, but we should also do this for sizeOf and alignment in Foreign.Storable. On Dec 13, 2017 10:53 PM, "M Farkas-Dyck" wrote: > I propose to add the following methods to `Bits` and `FiniteBits` classes: > > class Bits a where > ... > > bitSizeMaybe' :: Proxy a -> Maybe Int > > class FiniteBits b where > ... > > finiteBitSize' :: Proxy b -> Int > > Rationale: working with an arbitrary `Bits a => a`, one may not have a > value of type `a` as argument to `bitSizeMaybe` or `finiteBitSize`, and > writing `undefined` makes me feel dirty. > _______________________________________________ > 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 14 04:22:04 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 13 Dec 2017 23:22:04 -0500 Subject: Proposal: `Enum` class overhaul In-Reply-To: References: Message-ID: I'm moderately opposed, on the basis that the Enum class is too fundamentally broken/meaningless to be worth fiddling with. It attempts to serve multiple barely-related purposes at once, and serves none of them terribly well. On Dec 13, 2017 11:17 PM, "M Farkas-Dyck" wrote: > I propose to add some new methods of `Enum`: > > class Enum a where > ... > > predMay, succMay :: a -> Maybe a > toEnum' :: Integer -> Maybe a > fromEnum' a -> Integer > > Rationale for `fromEnum'` and `toEnum'`: > > The docs for `Enum` now say the minimal complete definition is `toEnum` > and `fromEnum`, but this is not enough to have sane default instances of > the other methods, for example: > > data ABC = A | B | C deriving Show > instance Enum ABC where > toEnum 0 = A > toEnum 1 = B > toEnum 2 = C > fromEnum A = 0 > fromEnum B = 1 > fromEnum C = 2 > > main = print [A ..] -- [A,B,C,*** Exception: Non-exhaustive patterns in > function toEnum > > In this case one could merely derive `Enum`, but not in some other cases, > e.g. numeric types or GADTs. It is not possible to do better defining > `toEnum` and `fromEnum` alone. > > If we default-define `toEnum'` and `fromEnum'` and their evil (i.e. > partial) syblings in terms of each other, the user need merely define the > total methods. > > Using `Integer` rather than `Int` allows these methods to not fail for > types larger than an `Int`, which are not uncommon on 32-bit systems. > > Rationale for `predMay` and `succMay`: > > I include these partly for completeness, but `predMay` can not now be > defined in general, and `succMay` only cumbersomely in terms of `enumFrom`. > > Note: All rationales imply "unless one uses `unsafePerformIO`". I'd rather > not, myself. > > _______________________________________________ > 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 strake888 at gmail.com Thu Dec 14 04:41:47 2017 From: strake888 at gmail.com (M Farkas-Dyck) Date: Wed, 13 Dec 2017 20:41:47 -0800 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: <364f4c4f-1912-b8c0-ce0a-2c81c1050b9b@gmail.com> On 2017-12-13 08:19 PM, David Feuer wrote: > +1, but we should also do this for sizeOf and alignment in Foreign.Storable. Yes, good idea From strake888 at gmail.com Thu Dec 14 04:46:21 2017 From: strake888 at gmail.com (M Farkas-Dyck) Date: Wed, 13 Dec 2017 20:46:21 -0800 Subject: Proposal: `Enum` class overhaul In-Reply-To: References: Message-ID: <33363a0e-bc17-7d0a-9722-592312f96a96@gmail.com> On 2017-12-13 08:22 PM, David Feuer wrote: > I'm moderately opposed, on the basis that the Enum class is too fundamentally broken/meaningless to be worth fiddling with. It attempts to serve multiple barely-related purposes at once, and serves none of them terribly well. I agree it's bad, but `..` syntax is defined in terms of it, and trying to introduce breaking modifications into base is like trying to introduce my head into a brick wall. From zemyla at gmail.com Thu Dec 14 05:37:47 2017 From: zemyla at gmail.com (Zemyla) Date: Wed, 13 Dec 2017 23:37:47 -0600 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: <364f4c4f-1912-b8c0-ce0a-2c81c1050b9b@gmail.com> References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> <364f4c4f-1912-b8c0-ce0a-2c81c1050b9b@gmail.com> Message-ID: I honestly think we should make it a Const Int a, instead of a function, so that it's a number in the typeclass dictionary and not a function. On Wed, Dec 13, 2017 at 10:41 PM, M Farkas-Dyck wrote: > On 2017-12-13 08:19 PM, David Feuer wrote: >> >> +1, but we should also do this for sizeOf and alignment in >> Foreign.Storable. > > > Yes, good idea > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries From tikhon at jelv.is Thu Dec 14 05:41:22 2017 From: tikhon at jelv.is (Tikhon Jelvis) Date: Wed, 13 Dec 2017 21:41:22 -0800 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> <364f4c4f-1912-b8c0-ce0a-2c81c1050b9b@gmail.com> Message-ID: The Const type does not see much direct use in other common Haskell packages. (I only ever encounter it through lens.) So while that might be an elegant design, I think it will make the API more confusing for newcomers. On Dec 13, 2017 9:38 PM, "Zemyla" wrote: > I honestly think we should make it a Const Int a, instead of a > function, so that it's a number in the typeclass dictionary and not a > function. > > On Wed, Dec 13, 2017 at 10:41 PM, M Farkas-Dyck > wrote: > > On 2017-12-13 08:19 PM, David Feuer wrote: > >> > >> +1, but we should also do this for sizeOf and alignment in > >> Foreign.Storable. > > > > > > Yes, good idea > > > > _______________________________________________ > > 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 strake888 at gmail.com Thu Dec 14 07:09:00 2017 From: strake888 at gmail.com (M Farkas-Dyck) Date: Wed, 13 Dec 2017 23:09:00 -0800 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> <364f4c4f-1912-b8c0-ce0a-2c81c1050b9b@gmail.com> Message-ID: On 2017-12-13 09:37 PM, Zemyla wrote: > I honestly think we should make it a Const Int a, instead of a > function, so that it's a number in the typeclass dictionary and not a > function. I like that idea! On 2017-12-13 09:41 PM, Tikhon Jelvis wrote: > The Const type does not see much direct use in other common Haskell packages. (I only ever encounter it through lens.) So while that might be an elegant design, I think it will make the API more confusing for newcomers. I doubt whether it's much more confusing than `Proxy`, and would be more efficient in cases where the typeclass dictionary can't be inline. Anyhow, if we began using it in base it would thus gain exposure; it's self-fulfilling either way. From lemming at henning-thielemann.de Thu Dec 14 08:36:57 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Thu, 14 Dec 2017 09:36:57 +0100 (CET) Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: On Wed, 13 Dec 2017, David Feuer wrote: > +1, but we should also do this for sizeOf and alignment in Foreign.Storable. That was my intended reply ... From lemming at henning-thielemann.de Thu Dec 14 08:38:46 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Thu, 14 Dec 2017 09:38:46 +0100 (CET) Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> <364f4c4f-1912-b8c0-ce0a-2c81c1050b9b@gmail.com> Message-ID: On Wed, 13 Dec 2017, Zemyla wrote: > I honestly think we should make it a Const Int a, instead of a function, > so that it's a number in the typeclass dictionary and not a function. Even better. From lemming at henning-thielemann.de Thu Dec 14 08:43:57 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Thu, 14 Dec 2017 09:43:57 +0100 (CET) Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: On Wed, 13 Dec 2017, M Farkas-Dyck wrote: > I propose to add the following methods to `Bits` and `FiniteBits` classes: > > class Bits a where > ... > > bitSizeMaybe' :: Proxy a -> Maybe Int > > class FiniteBits b where > ... > > finiteBitSize' :: Proxy b -> Int Alternative suggestion for names (I frequently overlook the primes): bitSizeMaybeConst :: Const (Maybe Int) a finiteBitSizeConst :: Const Int a sizeOfConst :: Const Int a alignmentConst :: Const Int a Then we must add mutual default implementations in order to preserve existing instances. From simonpj at microsoft.com Thu Dec 14 10:12:03 2017 From: simonpj at microsoft.com (Simon Peyton Jones) Date: Thu, 14 Dec 2017 10:12:03 +0000 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: Now that we have visible type application, we could stop using these Proxy arguments, thus class Bits a where ... bitSizeMaybe' :: Maybe Int And you invoke it by saying bitSizeMaybe @ T rather than bitSizeMaybe (Proxy :: Proxy T) Looks like a straight win to me. Simon | -----Original Message----- | From: Libraries [mailto:libraries-bounces at haskell.org] On Behalf Of M | Farkas-Dyck | Sent: 14 December 2017 03:48 | To: libraries at haskell.org | Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and | `finiteBitSize` | | I propose to add the following methods to `Bits` and `FiniteBits` | classes: | | class Bits a where | ... | | bitSizeMaybe' :: Proxy a -> Maybe Int | | class FiniteBits b where | ... | | finiteBitSize' :: Proxy b -> Int | | Rationale: working with an arbitrary `Bits a => a`, one may not have a | value of type `a` as argument to `bitSizeMaybe` or `finiteBitSize`, | and writing `undefined` makes me feel dirty. | _______________________________________________ | Libraries mailing list | Libraries at haskell.org | https://na01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.h | askell.org%2Fcgi- | bin%2Fmailman%2Flistinfo%2Flibraries&data=04%7C01%7Csimonpj%40microsof | t.com%7Cd88222263d04465efcf608d542a6473f%7C72f988bf86f141af91ab2d7cd01 | 1db47%7C1%7C0%7C636488204282827644%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4 | wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwifQ%3D%3D%7C- | 1&sdata=GUcUpHRarbB8uky4m%2Fve1l3ZbtPnDIndzPM9FG5Jj44%3D&reserved=0 From andrew.thaddeus at gmail.com Thu Dec 14 12:16:08 2017 From: andrew.thaddeus at gmail.com (Andrew Martin) Date: Thu, 14 Dec 2017 07:16:08 -0500 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> <364f4c4f-1912-b8c0-ce0a-2c81c1050b9b@gmail.com> Message-ID: Alternatively, we could have it be `Proxy# a -> Int`, which should have identical performance characteristics to `Const Int a` but with the added benefit that it's a little easier to understand how it's supposed to be used. On Thu, Dec 14, 2017 at 12:37 AM, Zemyla wrote: > I honestly think we should make it a Const Int a, instead of a > function, so that it's a number in the typeclass dictionary and not a > function. > > On Wed, Dec 13, 2017 at 10:41 PM, M Farkas-Dyck > wrote: > > On 2017-12-13 08:19 PM, David Feuer wrote: > >> > >> +1, but we should also do this for sizeOf and alignment in > >> Foreign.Storable. > > > > > > Yes, good idea > > > > _______________________________________________ > > 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 ryan.gl.scott at gmail.com Thu Dec 14 13:15:02 2017 From: ryan.gl.scott at gmail.com (Ryan Scott) Date: Thu, 14 Dec 2017 08:15:02 -0500 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` Message-ID: I don't have a particular opinion on this proposal, but I did want to chime in to note that there are several other functions in base besides biteSizeMaybe, finiteBitSize, sizeOf, and alignment that take a dummy argument. The last time I checked, all of these functions also fit the bill [1]: * Data.Bits.isSigned :: Bits a => a -> Bool * Data.Data.dataTypeOf :: Data a => a -> DataType * GHC.Generics.datatypeName :: Datatype d => t d f a -> String * GHC.Generics.moduleName :: Datatype d => t d f a -> String * GHC.Generics.isNewtype :: Datatype d => t d f a -> Bool * GHC.Generics.packageName :: Datatype d => t d f a -> String * GHC.Generics.conName :: Constructor c => t c f a -> String * GHC.Generics.conFixity :: Constructor c => t c f a -> Fixity * GHC.Generics.conIsRecord :: Constructor c => t c f a -> Bool * GHC.Generics.selName :: Selector s => t s f a -> String * GHC.Generics.selSourceUnpackedness :: Selector s => t s f a -> SourceUnpackedness * GHC.Generics.selSourceStrictness :: Selector s => t s f a -> SourceStrictness * GHC.Generics.selDecidedStrictness :: Selector s => t s f a -> DecidedStrictness * Prelude.floatRadix :: RealFloat => a -> Integer * Prelude.floatDigits :: RealFloat => a -> (Int, Int) * Text.Printf :: PrintfArg a => a -> ModifierParser Ryan S. ----- [1] This list was taken from http://hackage.haskell.org/package/proxied-0.3/docs/Data-Proxied.html From lemming at henning-thielemann.de Thu Dec 14 13:46:52 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Thu, 14 Dec 2017 14:46:52 +0100 (CET) Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: On Thu, 14 Dec 2017, Simon Peyton Jones via Libraries wrote: > Now that we have visible type application, we could stop using these Proxy arguments, thus > > class Bits a where > ... > bitSizeMaybe' :: Maybe Int > > And you invoke it by saying > bitSizeMaybe @ T > rather than > bitSizeMaybe (Proxy :: Proxy T) > > Looks like a straight win to me. I was not aware of this type extension, but I still prefer Haskell 98 / 2010. From strake888 at gmail.com Thu Dec 14 20:11:19 2017 From: strake888 at gmail.com (M Farkas-Dyck) Date: Thu, 14 Dec 2017 12:11:19 -0800 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: <623ce720-4bda-c046-09cd-f8c1144e1425@gmail.com> On 2017-12-14 05:46 AM, Henning Thielemann wrote: > I still prefer Haskell 98 / 2010. I agree. I would hesitate to introduce ambiguous types here. From ekmett at gmail.com Fri Dec 15 14:08:22 2017 From: ekmett at gmail.com (Edward Kmett) Date: Fri, 15 Dec 2017 09:08:22 -0500 Subject: Proposal: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize` In-Reply-To: <623ce720-4bda-c046-09cd-f8c1144e1425@gmail.com> References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> <623ce720-4bda-c046-09cd-f8c1144e1425@gmail.com> Message-ID: This was my knee-jerk reaction as well, but interestingly, you only actually need to turn on AllowAmbiguousTypes to compile the class. You can actually _use_ the methods without the extension. This matters to me because AllowAmbiguousTypes allows far too many errors through in user code. This renders it a somewhat less bad option than I previously assumed and leaves me somewhat ambivalent about whether we use the extension or not. On Thu, Dec 14, 2017 at 3:11 PM, M Farkas-Dyck wrote: > On 2017-12-14 05:46 AM, Henning Thielemann wrote: > >> I still prefer Haskell 98 / 2010. >> > > I agree. I would hesitate to introduce ambiguous types here. > > _______________________________________________ > 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 Sat Dec 16 03:22:18 2017 From: david.feuer at gmail.com (David Feuer) Date: Fri, 15 Dec 2017 22:22:18 -0500 Subject: Discussion: Storable instances for tuples In-Reply-To: References: Message-ID: It seems surprising that there are no Storable instances for tuple types. I would expect any tuple of Storable types to be Storable. To provide a sensible FFI experience, the order of the fields should be preserved. Since Storable generally aligns values, I believe elements should be aligned within tuples as well, in the default fashion used for C structs. We could offer a Packed newtype to override this behavior. Why store tuples like this, and not the way Data.Vector.Unboxed does? A moment's reflection will show that it simply can't. A Ptr is a single pointer and must remain one; there's no room in it to deal with multiple arrays or extra offset info. -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Sat Dec 16 05:33:36 2017 From: david.feuer at gmail.com (David Feuer) Date: Sat, 16 Dec 2017 00:33:36 -0500 Subject: Storable laws In-Reply-To: References: Message-ID: The documentation for pokeByteOff indicates that the following equality holds: pokeElemOff addr idx x = poke (addr `plusPtr` (idx * sizeOf x)) x Notably, this ignores alignment. It thus seems to imply that sizeOf must always be a multiple of alignment; otherwise, non-zero indices could access non-aligned addresses. Was this intentional? If so, I believe sizeOf and alignment should document the law. If not, then I believe the {poke,peek}ElemOff laws need to change to something like pokeElemOff addr idx x = poke (addr `plusPtr` (idx * lcm (sizeOf x) (alignment x))) x -------------- next part -------------- An HTML attachment was scrubbed... URL: From mgsloan at gmail.com Sat Dec 16 05:59:37 2017 From: mgsloan at gmail.com (Michael Sloan) Date: Fri, 15 Dec 2017 21:59:37 -0800 Subject: Storable laws In-Reply-To: References: Message-ID: I realize that these libraries are used on many architectures. However, on modern x86 machines, that are less than ~7 years old, it doesn't seem to matter all that much. https://lemire.me/blog/2012/05/31/data-alignment-for-speed-myth-or-reality/ In the comments, looks like somewhat older processors take a 40% performance hit, which isn't good, but it isn't awful. IIRC, of the processors that are actually used, there are two where access alignment really matters - ARM and PowerPC. If you're running linux I believe it will handle the exception and do the unaligned access. However, of course it's really slow to do this. I'm not sure if it makes sense to change the law. Someone might be relying on the behavior of instances that do not fulfill this law. Perhaps in those cases it makes sense to just remove the instance. -Michael On Fri, Dec 15, 2017 at 9:33 PM, David Feuer wrote: > The documentation for pokeByteOff indicates that the following equality > holds: > > pokeElemOff addr idx x = > poke (addr `plusPtr` (idx * sizeOf x)) x > > Notably, this ignores alignment. It thus seems to imply that sizeOf must > always be a multiple of alignment; otherwise, non-zero indices could access > non-aligned addresses. > > Was this intentional? If so, I believe sizeOf and alignment should document > the law. If not, then I believe the {poke,peek}ElemOff laws need to change > to something like > > pokeElemOff addr idx x = > poke (addr `plusPtr` (idx * lcm (sizeOf x) (alignment x))) x > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From lemming at henning-thielemann.de Sat Dec 16 07:49:51 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sat, 16 Dec 2017 08:49:51 +0100 (CET) Subject: Discussion: Storable instances for tuples In-Reply-To: References: Message-ID: On Fri, 15 Dec 2017, David Feuer wrote: > It seems surprising that there are no Storable instances for tuple types. I would expect any tuple of Storable > types to be Storable. To provide a sensible FFI experience, the order of the fields should be preserved. Since > Storable generally aligns values, I believe elements should be aligned within tuples as well, in the default > fashion used for C structs. We could offer a Packed newtype to override this behavior. I had the same suggestion when we discussed instance Storable (). Sven Panne answered: http://mail.haskell.org/pipermail/libraries/2015-June/025903.html From lemming at henning-thielemann.de Sat Dec 16 07:53:52 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sat, 16 Dec 2017 08:53:52 +0100 (CET) Subject: Storable laws In-Reply-To: References: Message-ID: On Fri, 15 Dec 2017, Michael Sloan wrote: > I'm not sure if it makes sense to change the law. Someone might be > relying on the behavior of instances that do not fulfill this law. > Perhaps in those cases it makes sense to just remove the instance. Storable is intended for data exchange with code written in other languages. Thus we must use the same alignment rules as the system ABI. From svenpanne at gmail.com Sat Dec 16 13:33:05 2017 From: svenpanne at gmail.com (Sven Panne) Date: Sat, 16 Dec 2017 14:33:05 +0100 Subject: Storable laws In-Reply-To: References: Message-ID: 2017-12-16 6:33 GMT+01:00 David Feuer : > The documentation for pokeByteOff indicates that the following equality > holds: > > pokeElemOff addr idx x = > poke (addr `plusPtr` (idx * sizeOf x)) x > > [...] Was this intentional? > Yep, that was intentional, think of pokeElemOff as indexing into an array. Note that the FFI intentionally does not specify how to (un)marshal structs, only basic types and arrays of them. Doing anything else would be a) language-specific and b) platform-ABI-specific. Storable is just meant as a basic building block to do such more involved things. > If so, I believe sizeOf and alignment should document the law. [...] > Perhaps, but what exactly do you feel is missing there? -------------- next part -------------- An HTML attachment was scrubbed... URL: From svenpanne at gmail.com Sat Dec 16 14:06:53 2017 From: svenpanne at gmail.com (Sven Panne) Date: Sat, 16 Dec 2017 15:06:53 +0100 Subject: Storable laws In-Reply-To: References: Message-ID: 2017-12-16 8:53 GMT+01:00 Henning Thielemann : > Storable is intended for data exchange with code written in other > languages. Thus we must use the same alignment rules as the system ABI. As already mentioned above, Storable is meant as a *basic* building block for doing that, without a reference to any ABI whatsoever. Another use case for Storable is e.g. marshaling things into some form suitable for serialization, which might have nothing to do with any system ABI. So the conclusion that Storable must somehow obey some alignment rules is not correct: *You* as the author of a Storable instance for a give purpose have to care about alignment/packing/etc. Taking a step back: An ABI like https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf specifies a lot of things: * OS interface * File formats * Handling of exceptions * Linking * The calling convention for C (data types, data layout, registers, stack frames, ...) * ... Even the calling convention for C++ is left out of most such ABI documents (perhaps available as a separate addendum), other languages are most of the time not even mentioned. *Some* calling convention has to be specified, otherwise you would have a hard time specifying the OS interface, and C is still the most natural choice for that. The FFI spec just gives you a small fraction of such an ABI: * A way to call C land, because you can't construct the right stack frame/register contents from Haskell land * A way to call back from C to Haskell * A very basic tooling to (un)marshal primitive data types and arrays of them (Storable) Note that Storable itself is intentionally not tied to the ABI, it could as well be used to e.g. marshal packed graphics data to OpenGL etc. The right approach IMHO is to have separate classes for the various ABIs: * StorableAMD64 * Storablex86 * StorableARM32 * StorableARM64 * ... Those classes would handle alignment/ordering issues for their respective platform, and we can have more instances for them, including sum types. Perhaps even a packed variant of these classes might be needed. In addition, perhaps an alias (subclass?) "StorableNative" of one of those classes represents the native ABI on the platform the program is running is needed, but then cross-compilation will be tricky. I'm very open to extending the FFI toolset, but let's not retroactively interpret stuff into already existing things, at the danger of breaking an unknown amount of code. Cheers, S. -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Sat Dec 16 14:16:29 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sat, 16 Dec 2017 15:16:29 +0100 (CET) Subject: Storable laws In-Reply-To: References: Message-ID: On Sat, 16 Dec 2017, Sven Panne wrote: > 2017-12-16 6:33 GMT+01:00 David Feuer : > The documentation for pokeByteOff indicates that the following equality holds: > >   pokeElemOff addr idx x = >     poke (addr `plusPtr` (idx * sizeOf x)) x > > [...] Was this intentional? > > > Yep, that was intentional, think of pokeElemOff as indexing into an > array. Note that the FFI intentionally does not specify how to > (un)marshal structs, only basic types and arrays of them. I thought that arrays require alignment of their elements. From svenpanne at gmail.com Sat Dec 16 14:41:13 2017 From: svenpanne at gmail.com (Sven Panne) Date: Sat, 16 Dec 2017 15:41:13 +0100 Subject: Storable laws In-Reply-To: References: Message-ID: 2017-12-16 15:16 GMT+01:00 Henning Thielemann : > I thought that arrays require alignment of their elements. Yes, and if you start aligned, the pokeElemOff law keeps you aligned. If you don't start aligned, Storable never magically aligns the first element, anyway, so this must have been intentional (e.g. an array within packed data). In theory one could have an e.g. 7-byte data type with 8-byte alignment requirements, but I think we can re-open the discussion when a processor manufacturer is masochistic enough to do that. ;-) -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Sat Dec 16 15:45:59 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sat, 16 Dec 2017 16:45:59 +0100 (CET) Subject: Storable laws In-Reply-To: References: Message-ID: On Sat, 16 Dec 2017, Sven Panne wrote: > 2017-12-16 15:16 GMT+01:00 Henning Thielemann : > I thought that arrays require alignment of their elements. > > > Yes, and if you start aligned, the pokeElemOff law keeps you aligned. If you don't start aligned, Storable never > magically aligns the first element, anyway, so this must have been intentional (e.g. an array within packed > data). > > In theory one could have an e.g. 7-byte data type with 8-byte alignment requirements, but I think we can re-open > the discussion when a processor manufacturer is masochistic enough to do that. ;-) I more think of a custom struct with size 12 bytes consisting of a 64 bit and 32 bit word. It must be 8-byte aligned. You would have to align all elements at multiples of 8-byte and the address difference between two array elements is 16 not 12. On x86 Linux there would be no problem because a 12 byte struct containing a 64 bit word must already be padded to 16 byte. But that's an ABI definition and Storable wants to keep independent from that, right? From svenpanne at gmail.com Sat Dec 16 16:02:23 2017 From: svenpanne at gmail.com (Sven Panne) Date: Sat, 16 Dec 2017 17:02:23 +0100 Subject: Storable laws In-Reply-To: References: Message-ID: 2017-12-16 16:45 GMT+01:00 Henning Thielemann : > I more think of a custom struct with size 12 bytes consisting of a 64 bit > and 32 bit word. It must be 8-byte aligned. You would have to align all > elements at multiples of 8-byte and the address difference between two > array elements is 16 not 12. > > On x86 Linux there would be no problem because a 12 byte struct containing > a 64 bit word must already be padded to 16 byte. But that's an ABI > definition and Storable wants to keep independent from that, right? > Yes, that's an ABI issue. Once again: Storable is *not* for structs, it never has been and will never be (because there is no single correct instance for composite struct-like types). Without any further assumptions, the gap-less definition is the only one which makes sense. And without instances for struct-like things, it even makes more sense. So what you want is an instance of the proposed StorableAMD64 class. Taking your example: An array without gaps of your 12byte struct would e.g. be totally OK for OpenGL or a packed AMD64-conformant struct, so base shouldn't choose one for you. -------------- next part -------------- An HTML attachment was scrubbed... URL: From lemming at henning-thielemann.de Sat Dec 16 16:09:03 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sat, 16 Dec 2017 17:09:03 +0100 (CET) Subject: Storable laws In-Reply-To: References: Message-ID: On Sat, 16 Dec 2017, Sven Panne wrote: > Yes, that's an ABI issue. Once again: Storable is *not* for structs, it > never has been and will never be (because there is no single correct > instance for composite struct-like types). One of hsc2hs most important tasks is to generate Storable instances of Haskell records that shall be compatible to C structs. Is that one completely invalid? From lemming at henning-thielemann.de Sun Dec 17 12:41:09 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Sun, 17 Dec 2017 13:41:09 +0100 (CET) Subject: Storable laws In-Reply-To: References: Message-ID: On Sun, 17 Dec 2017, Merijn Verstraaten wrote: > Tools like hsc2hs already pad the result of sizeOf to the appropriately > aligned size (at least the ones I've used), so this is a non-issue for > that scenario. But that's tailored to C. If I understand Sven correctly, then this is not valid for Storable. From svenpanne at gmail.com Sun Dec 17 19:02:09 2017 From: svenpanne at gmail.com (Sven Panne) Date: Sun, 17 Dec 2017 20:02:09 +0100 Subject: Storable laws In-Reply-To: References: Message-ID: 2017-12-17 13:41 GMT+01:00 Henning Thielemann : > > On Sun, 17 Dec 2017, Merijn Verstraaten wrote: > > Tools like hsc2hs already pad the result of sizeOf to the appropriately >> aligned size (at least the ones I've used), so this is a non-issue for that >> scenario. >> > > But that's tailored to C. If I understand Sven correctly, then this is not > valid for Storable. I'm not sure if I understand the concerns about hsc2hs here correctly, but anyway: There are intentionally no Storable instances for struct-like things in the FFI spec, but that doesn't rule out that one can define instances for a special purpose (e.g. native ABI compliant ones) on your own. hsc2hs, c2hs, GreenCard etc. are tools to help you with that (and much more). This doesn't contradict anything in the FFI spec, you just choose one of several possible semantics in your program for types which are not even mentioned in the spec. OTOH, as an author of a general library I would be very hesitant to define such instances, they might not be what the library user expects. Perhaps we really want to extend the FFI spec in such a way that only one kind of instance makes sense for a given type (including complex ones), e.g. by defining separate classes for the different purposes mentioned in this thread. But this would need some serious design thoughts to get this right and flexible enough while avoiding to break tons of FFI code already out there. -------------- next part -------------- An HTML attachment was scrubbed... URL: From qdunkan at gmail.com Sun Dec 17 19:20:00 2017 From: qdunkan at gmail.com (Evan Laforge) Date: Sun, 17 Dec 2017 11:20:00 -0800 Subject: Storable laws In-Reply-To: References: Message-ID: This is only roughly related, but long ago I completely replaced Storable in my own hsc2hs-using code with CStorable, which is a copy of Storable, except having only the instances that I choose. Specifically, it has instances for CChar but not Char, for CBool but not Bool, etc. because it's too dangerous to silently allow these memory-corrupting instances. I think reusing Storable for C serialization was a mistake. Replacing Storable was pretty easy though, just copy-paste the 200-line Foreign module and change the class name. On Sun, Dec 17, 2017 at 11:02 AM, Sven Panne wrote: > 2017-12-17 13:41 GMT+01:00 Henning Thielemann > : >> >> >> On Sun, 17 Dec 2017, Merijn Verstraaten wrote: >> >>> Tools like hsc2hs already pad the result of sizeOf to the appropriately >>> aligned size (at least the ones I've used), so this is a non-issue for that >>> scenario. >> >> >> But that's tailored to C. If I understand Sven correctly, then this is not >> valid for Storable. > > > I'm not sure if I understand the concerns about hsc2hs here correctly, but > anyway: There are intentionally no Storable instances for struct-like things > in the FFI spec, but that doesn't rule out that one can define instances for > a special purpose (e.g. native ABI compliant ones) on your own. hsc2hs, > c2hs, GreenCard etc. are tools to help you with that (and much more). This > doesn't contradict anything in the FFI spec, you just choose one of several > possible semantics in your program for types which are not even mentioned in > the spec. OTOH, as an author of a general library I would be very hesitant > to define such instances, they might not be what the library user expects. > > Perhaps we really want to extend the FFI spec in such a way that only one > kind of instance makes sense for a given type (including complex ones), e.g. > by defining separate classes for the different purposes mentioned in this > thread. But this would need some serious design thoughts to get this right > and flexible enough while avoiding to break tons of FFI code already out > there. > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From lemming at henning-thielemann.de Mon Dec 18 07:55:24 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Mon, 18 Dec 2017 08:55:24 +0100 (CET) Subject: Storable laws In-Reply-To: References: Message-ID: On Sun, 17 Dec 2017, Evan Laforge wrote: > This is only roughly related, but long ago I completely replaced > Storable in my own hsc2hs-using code with CStorable, which is a copy > of Storable, except having only the instances that I choose. > Specifically, it has instances for CChar but not Char, for CBool but > not Bool, etc. because it's too dangerous to silently allow these > memory-corrupting instances. I think reusing Storable for C > serialization was a mistake. Replacing Storable was pretty easy > though, just copy-paste the 200-line Foreign module and change the > class name. Would you mind moving this class to a public package? From lemming at henning-thielemann.de Tue Dec 19 09:17:30 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 19 Dec 2017 10:17:30 +0100 (CET) Subject: Const versions of sizeOf and alignment (Was: add `Proxy`fied versions of `bitSizeMaybe` and `finiteBitSize`) In-Reply-To: References: <12c91ea8-2dde-90e7-276a-b71046d8dab5@gmail.com> Message-ID: On Wed, 13 Dec 2017, David Feuer wrote: > +1, but we should also do this for sizeOf and alignment in Foreign.Storable. If Storable would be intended for tuples, too, and there would be no padding, we could use special Monoids in Const, like so: class Storable a where sizeOf :: Const (Sum Int) a alignment :: Const (LCM Int) a instance (Storable a, Storable b) => Storable (a,b) where sizeOf = liftA2 (,) sizeOf sizeOf alignment = liftA2 (,) alignment alignment Taking alignment into account we could define data SizeAlign = SignAlign {sizeOf_, alignment_ :: Int} instance Monoid SizeAlign where mempty = SizeAlign 0 1 mappend x y = SizeAlign (sizeOf_ x + mod (- sizeOf_ x) (alignment_ y) + sizeOf_ y) (lcm (alignment_ x) (alignment_ y)) class Storable a where sizeAlign :: Const SizeAlign a instance (Storable a, Storable b) => Storable (a,b) where sizealign = liftA2 (,) sizeOf sizeOf However, SizeAlign.mappend this way is not valid because it violates associativity (e.g. sizes 1, 1, 2 with corresponding alignments). Even if it would be valid, it would still differ e.g. from Linux-x86 ABI, since structs are already padded to the next aligned size. At least for the alignments an LCM monoid would work. From victor at lopezjuan.com Tue Dec 19 11:04:33 2017 From: victor at lopezjuan.com (=?UTF-8?Q?V=c3=adctor_L=c3=b3pez_Juan?=) Date: Tue, 19 Dec 2017 12:04:33 +0100 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` Message-ID: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> Proposal: Add a method disjoint :: IntSet → IntSet → Bool, to Data.IntSet, such that prop> disjoint a b ≡ null (intersection a b) Alternatively or additionally, add a method overlaps :: IntSet -> IntSet -> Bool such that prop> a `overlaps` b ≡ not.null$ intersection a b Rationale: - I have found it useful to have such a method when keeping track of the set of free-variables in a term. I believe that there can be more use cases. - There are already similar specialized implementations in the library. For example, isSubsetOf :: IntSet -> IntSet -> Bool is such that prop> a `isSubsetOf` b ≡ (a == (a `intersection` b)). - Having `disjoint`, the user can also check whether two sets overlap with `(not.).disjoint`. This is shorter and more self-explaining than (not.null$ intersection). - A specialized implementation of `disjoint` (vs. (null.).intersection) can shortcircuit as soon as the sets overlap on one element. This leads to significant speed-ups; for example, 23× when checking that the sets {1,2,3…,2¹²} and {2,4,6,…,2¹²} are not disjoint [1]. Discussion: I would like to get some comments on this proposal. In particular: - Should any of these methods be added? - Should both `overlaps` and `disjoint` be added? - If only one of them is added, which one should it be? I hope a decision about the proposal can be reached before 2018-01-09. See also: - Proposed patch [2] - Previous discussion [3] [1] https://github.com/haskell/containers/pull/377#issuecomment-352585171 [2] https://github.com/haskell/containers/pull/377/files [3] https://github.com/haskell/containers/pull/377 From andreas.abel at ifi.lmu.de Tue Dec 19 12:44:09 2017 From: andreas.abel at ifi.lmu.de (Andreas Abel) Date: Tue, 19 Dec 2017 13:44:09 +0100 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> Message-ID: +1 for "disjoint". I think "overlaps" falls below the Fairbairn threshold. I always wondered why there is a "notMember" function in the Set interface, saving us 3 key presses. One thing to consider: Data.Set should then also be equipped with a function "disjoint", to keep interfaces in sync. Best, Andreas On 19.12.2017 12:04, Víctor López Juan wrote: > Proposal: > > Add a method disjoint :: IntSet → IntSet → Bool, > to Data.IntSet, such that > prop> disjoint a b ≡ null (intersection a b) > > Alternatively or additionally, add a method > overlaps :: IntSet -> IntSet -> Bool > such that > prop> a `overlaps` b ≡ not.null$ intersection a b > > Rationale: > > - I have found it useful to have such a method when keeping track of the > set of free-variables in a term. I believe that there can be more use > cases. > > - There are already similar specialized implementations in the library. > For example, isSubsetOf :: IntSet -> IntSet -> Bool is such that > prop> a `isSubsetOf` b ≡ (a == (a `intersection` b)). > > - Having `disjoint`, the user can also check whether two sets overlap > with `(not.).disjoint`. This is shorter and more self-explaining than > (not.null$ intersection). > > - A specialized implementation of `disjoint` (vs. (null.).intersection) > can shortcircuit as soon as the sets overlap on one element. This leads > to significant speed-ups; for example, 23× when checking that the sets > {1,2,3…,2¹²} and {2,4,6,…,2¹²} are not disjoint [1]. > > Discussion: > > I would like to get some comments on this proposal. In particular: > > - Should any of these methods be added? > - Should both `overlaps` and `disjoint` be added? > - If only one of them is added, which one should it be? > > I hope a decision about the proposal can be reached before 2018-01-09. > > See also: > - Proposed patch [2] > - Previous discussion [3] > > [1] https://github.com/haskell/containers/pull/377#issuecomment-352585171 > [2] https://github.com/haskell/containers/pull/377/files > [3] https://github.com/haskell/containers/pull/377 > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www.cse.chalmers.se/~abela/ From andrew.thaddeus at gmail.com Tue Dec 19 13:48:57 2017 From: andrew.thaddeus at gmail.com (Andrew Martin) Date: Tue, 19 Dec 2017 08:48:57 -0500 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> Message-ID: I'm +1 on disjoint and -1 on overlaps since someone can just write `not (disjoint x y)`. On Tue, Dec 19, 2017 at 6:04 AM, Víctor López Juan wrote: > Proposal: > > Add a method disjoint :: IntSet → IntSet → Bool, > to Data.IntSet, such that > prop> disjoint a b ≡ null (intersection a b) > > Alternatively or additionally, add a method > overlaps :: IntSet -> IntSet -> Bool > such that > prop> a `overlaps` b ≡ not.null$ intersection a b > > Rationale: > > - I have found it useful to have such a method when keeping track of the > set of free-variables in a term. I believe that there can be more use > cases. > > - There are already similar specialized implementations in the library. > For example, isSubsetOf :: IntSet -> IntSet -> Bool is such that > prop> a `isSubsetOf` b ≡ (a == (a `intersection` b)). > > - Having `disjoint`, the user can also check whether two sets overlap > with `(not.).disjoint`. This is shorter and more self-explaining than > (not.null$ intersection). > > - A specialized implementation of `disjoint` (vs. (null.).intersection) > can shortcircuit as soon as the sets overlap on one element. This leads > to significant speed-ups; for example, 23× when checking that the sets > {1,2,3…,2¹²} and {2,4,6,…,2¹²} are not disjoint [1]. > > Discussion: > > I would like to get some comments on this proposal. In particular: > > - Should any of these methods be added? > - Should both `overlaps` and `disjoint` be added? > - If only one of them is added, which one should it be? > > I hope a decision about the proposal can be reached before 2018-01-09. > > See also: > - Proposed patch [2] > - Previous discussion [3] > > [1] https://github.com/haskell/containers/pull/377#issuecomment-352585171 > [2] https://github.com/haskell/containers/pull/377/files > [3] https://github.com/haskell/containers/pull/377 > _______________________________________________ > 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 mail at joachim-breitner.de Tue Dec 19 15:01:54 2017 From: mail at joachim-breitner.de (Joachim Breitner) Date: Tue, 19 Dec 2017 10:01:54 -0500 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> Message-ID: <1513695714.1051.13.camel@joachim-breitner.de> Hi, Am Dienstag, den 19.12.2017, 13:44 +0100 schrieb Andreas Abel: > +1 for "disjoint". +1 > I think "overlaps" falls below the Fairbairn threshold. ✓ > I always > wondered why there is a "notMember" function in the Set interface, > saving us 3 key presses. Probably because of use like this: filter (`notMember` seen) todo -- pretty vs. filter (not . (`member` seen)) todo -- too many parenthesis. Of course filter (\x -> not (x `member` seen)) todo -- is also ok And I will refrain from pointing out that with the idea of no-white- space-means-higher-precedence[1] would allow filter (not . `member`seen) todo -- too many parenthesis. [1] https://www.joachim-breitner.de/blog/730-Less_parentheses > One thing to consider: Data.Set should then also be equipped with a > function "disjoint", to keep interfaces in sync. ✓ Cheers, Joachim -- Joachim Breitner mail at joachim-breitner.de http://www.joachim-breitner.de/ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 833 bytes Desc: This is a digitally signed message part URL: From victor at lopezjuan.com Tue Dec 19 15:18:43 2017 From: victor at lopezjuan.com (=?UTF-8?Q?V=c3=adctor_L=c3=b3pez_Juan?=) Date: Tue, 19 Dec 2017 16:18:43 +0100 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: <1513695714.1051.13.camel@joachim-breitner.de> References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> <1513695714.1051.13.camel@joachim-breitner.de> Message-ID: I'm thinking that `disjoint` is already a negation: (dis- (not) + joint (united)). When composing with `not`, the user gets a double negation `not (disjoint x y)`. There is a then a small mental effort required to go from "not disjoint" to "overlapping". If we are going to have only one of the two properties, I would rather have the positive one (`overlaps`) as primitive. Then `disjoint` would be written "not (overlaps x y)", which reads quite easily. (Or even "not (x `overlaps` y)"). — Víctor Den 2017-12-19 kl. 16:01, skrev Joachim Breitner: > Hi, > > Am Dienstag, den 19.12.2017, 13:44 +0100 schrieb Andreas Abel: >> +1 for "disjoint". > > > +1 > >> I think "overlaps" falls below the Fairbairn threshold. > > ✓ > >> I always >> wondered why there is a "notMember" function in the Set interface, >> saving us 3 key presses. > > Probably because of use like this: > > filter (`notMember` seen) todo -- pretty > > vs. > > filter (not . (`member` seen)) todo -- too many parenthesis. > > Of course > > filter (\x -> not (x `member` seen)) todo -- is also ok > > And I will refrain from pointing out that with the idea of no-white- > space-means-higher-precedence[1] would allow > > filter (not . `member`seen) todo -- too many parenthesis. > > > [1] https://www.joachim-breitner.de/blog/730-Less_parentheses > >> One thing to consider: Data.Set should then also be equipped with a >> function "disjoint", to keep interfaces in sync. > > ✓ > > Cheers, > Joachim > > > > _______________________________________________ > 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: OpenPGP digital signature URL: From lemming at henning-thielemann.de Tue Dec 19 15:44:20 2017 From: lemming at henning-thielemann.de (Henning Thielemann) Date: Tue, 19 Dec 2017 16:44:20 +0100 (CET) Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> <1513695714.1051.13.camel@joachim-breitner.de> Message-ID: On Tue, 19 Dec 2017, Víctor López Juan wrote: > I'm thinking that `disjoint` is already a negation: > (dis- (not) + joint (united)). When composing with `not`, the user gets > a double negation `not (disjoint x y)`. There is a then a small mental > effort required to go from "not disjoint" to "overlapping". > > If we are going to have only one of the two properties, I would rather > have the positive one (`overlaps`) as primitive. Then `disjoint` would > be written "not (overlaps x y)", which reads quite easily. > (Or even "not (x `overlaps` y)"). I also dislike double negation and think that 'disjoint' is one. I'd prefer to see both 'overlap' and 'disjoint'. From tikhon at jelv.is Tue Dec 19 18:01:01 2017 From: tikhon at jelv.is (Tikhon Jelvis) Date: Tue, 19 Dec 2017 10:01:01 -0800 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> <1513695714.1051.13.camel@joachim-breitner.de> Message-ID: In practice, I hear people talking about "disjoint" sets all the time—it comes up a lot more often than "overlapping" or "not overlapping". It might have a negative in the name semantically, but it's used as an atomic word in practice. (That is, when people say "disjoint" they're *thinking* "disjoint" as opposed to "not joint" or "not overlapping".) I'm in favor of naming functions with common usage in mind, and I think "disjoint" is the word people use most often in this context. On Tue, Dec 19, 2017 at 7:44 AM, Henning Thielemann < lemming at henning-thielemann.de> wrote: > > On Tue, 19 Dec 2017, Víctor López Juan wrote: > > I'm thinking that `disjoint` is already a negation: >> (dis- (not) + joint (united)). When composing with `not`, the user gets >> a double negation `not (disjoint x y)`. There is a then a small mental >> effort required to go from "not disjoint" to "overlapping". >> >> If we are going to have only one of the two properties, I would rather >> have the positive one (`overlaps`) as primitive. Then `disjoint` would >> be written "not (overlaps x y)", which reads quite easily. >> (Or even "not (x `overlaps` y)"). >> > > I also dislike double negation and think that 'disjoint' is one. I'd > prefer to see both 'overlap' and 'disjoint'. > _______________________________________________ > 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 abela at chalmers.se Tue Dec 19 23:45:28 2017 From: abela at chalmers.se (Andreas Abel) Date: Wed, 20 Dec 2017 00:45:28 +0100 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> <1513695714.1051.13.camel@joachim-breitner.de> Message-ID: I am thinking along the lines of Tikhon. Sets "overlap" is a rather uncommon term. [If we were all constructivists, the situation would be different. Constructively, "overlap" is certainly the primitive notion, and "disjoint" only its negation.] We can't introduce a positive term for everything. For instance, we all use not . null rather than having predicates like "isCons", "inhabited" etc. On 19.12.2017 19:01, Tikhon Jelvis wrote: > In practice, I hear people talking about "disjoint" sets all the time—it > comes up a lot more often than "overlapping" or "not overlapping". It > might have a negative in the name semantically, but it's used as an > atomic word in practice. (That is, when people say "disjoint" they're > *thinking* "disjoint" as opposed to "not joint" or "not overlapping".) > > I'm in favor of naming functions with common usage in mind, and I think > "disjoint" is the word people use most often in this context. > > On Tue, Dec 19, 2017 at 7:44 AM, Henning Thielemann > > > wrote: > > > On Tue, 19 Dec 2017, Víctor López Juan wrote: > > I'm thinking that `disjoint` is already a negation: > (dis- (not) + joint (united)). When composing with `not`, the > user gets > a double negation `not (disjoint x y)`. There is a then a small > mental > effort required to go from "not disjoint" to "overlapping". > > If we are going to have only one of the two properties, I would > rather > have the positive one (`overlaps`) as primitive. Then `disjoint` > would > be written "not (overlaps x y)", which reads quite easily. > (Or even "not (x `overlaps` y)"). > > > I also dislike double negation and think that 'disjoint' is one. I'd > prefer to see both 'overlap' and 'disjoint'. > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > > > > > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel at gu.se http://www.cse.chalmers.se/~abela/ From david.feuer at gmail.com Sat Dec 23 18:46:21 2017 From: david.feuer at gmail.com (David Feuer) Date: Sat, 23 Dec 2017 13:46:21 -0500 Subject: Adding a member to the Haskell organization In-Reply-To: References: Message-ID: Matt Renaud (GitHub user m-renaud) has agreed to join the containers maintenance team. Could someone with the power please add him to the Haskell organization on GitHub? -------------- next part -------------- An HTML attachment was scrubbed... URL: From hvriedel at gmail.com Sun Dec 24 13:20:44 2017 From: hvriedel at gmail.com (Herbert Valerio Riedel) Date: Sun, 24 Dec 2017 14:20:44 +0100 Subject: Adding a member to the Haskell organization In-Reply-To: References: Message-ID: Hi, On Sat, Dec 23, 2017 at 7:46 PM, David Feuer wrote: > Matt Renaud (GitHub user m-renaud) has agreed to join the containers > maintenance team. Could someone with the power please add him to the Haskell > organization on GitHub? done! From ryan.reich at gmail.com Wed Dec 27 07:33:09 2017 From: ryan.reich at gmail.com (Ryan Reich) Date: Tue, 26 Dec 2017 23:33:09 -0800 Subject: Constrained Dynamic variant Message-ID: I have found it useful to use Dynamic-like existential types such as (fake example): > data Number = forall a. (Num a, Typeable a) => Number a which supports precisely the same API as Dynamic, but with a Num constraint on everything. However, writing that API for this particular type requires copy-pasting the definitions of fromDyn and fromDynamic as boilerplate, which is (ahem) stupid. Now that we have the Constraint kind, it is possible to generalize this in a form suitable for Data.Dynamic: > data CDynamic (c :: Type -> Constraint) = forall a. (c a) => CDynamic (TypeRep a) a > > toCDyn :: (c a, Typeable a) => a -> CDynamic c > fromCDyn :: (c a, Typeable a) => CDynamic c -> a -> a > fromCDynamic :: (c a, Typeable a) => CDynamic c -> Maybe a > relaxCDyn :: CDynamic c -> Dynamic > dynApplyC :: CDynamic c1 -> CDynamic c2 -> Maybe Dynamic > dynAppC :: CDynamic c1 -> CDynamic c2 -> Dynamic > dynTypeRepC :: CDynamic c -> SomeTypeRep > > instance Show (CDynamic c) > instance Exception (CDynamic c) > > class NoC a where -- intentionally empty, can be used unsaturated > instance NoC a where -- also empty > type Dynamic = CDynamic NoC > > -- Specializations of all the above functions I think it's clear how to fill in the definitions. I added an apparently necessary function relaxCDyn that also does the obvious thing; I'm not really happy with its type signature but offhand I can't say how to generalize it. I think this is useful, and if I'm not missing anything (obvious or subtle) about it, I want to propose that it goes into Data.Dynamic. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ryan.reich at gmail.com Wed Dec 27 07:50:18 2017 From: ryan.reich at gmail.com (Ryan Reich) Date: Tue, 26 Dec 2017 23:50:18 -0800 Subject: Constraint implication Message-ID: The Constraint kind appears to lack an interface to an important capability that is already part of the type checker: constraint implication. Namely, the ability to provide a witness for the statement "constraint c1 implies constraint c2" or, more importantly, "for all a, constraint (c1 a) implies constraint (c2 a)", where c1 and c2 are now constraint-valued type functions (and possibly even for constraint functions with multiple parameters). It seems to me that this can follow the pattern of the "magic" Coercible type class and the (non-magic) Coercion data type; it provides the programmer with an analogous value to this example that can be obtained in apparently no other way. -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Wed Dec 27 08:16:52 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 27 Dec 2017 03:16:52 -0500 Subject: Constrained Dynamic variant In-Reply-To: References: Message-ID: You can make relaxation kind of work using a lens-like trick: type CDynamic (c :: * -> Constraint) = forall r. (forall a. (Typeable a, c a) => a -> r) -> r The trouble is that ambiguous types start to pop up pretty quickly, so I don't know that this would really be a practical approach. On Wed, Dec 27, 2017 at 2:33 AM, Ryan Reich wrote: > I have found it useful to use Dynamic-like existential types such as (fake > example): > >> data Number = forall a. (Num a, Typeable a) => Number a > > which supports precisely the same API as Dynamic, but with a Num constraint > on everything. However, writing that API for this particular type requires > copy-pasting the definitions of fromDyn and fromDynamic as boilerplate, > which is (ahem) stupid. Now that we have the Constraint kind, it is > possible to generalize this in a form suitable for Data.Dynamic: > >> data CDynamic (c :: Type -> Constraint) = forall a. (c a) => CDynamic >> (TypeRep a) a >> >> toCDyn :: (c a, Typeable a) => a -> CDynamic c >> fromCDyn :: (c a, Typeable a) => CDynamic c -> a -> a >> fromCDynamic :: (c a, Typeable a) => CDynamic c -> Maybe a >> relaxCDyn :: CDynamic c -> Dynamic >> dynApplyC :: CDynamic c1 -> CDynamic c2 -> Maybe Dynamic >> dynAppC :: CDynamic c1 -> CDynamic c2 -> Dynamic >> dynTypeRepC :: CDynamic c -> SomeTypeRep >> >> instance Show (CDynamic c) >> instance Exception (CDynamic c) >> >> class NoC a where -- intentionally empty, can be used unsaturated >> instance NoC a where -- also empty >> type Dynamic = CDynamic NoC >> >> -- Specializations of all the above functions > > I think it's clear how to fill in the definitions. I added an apparently > necessary function relaxCDyn that also does the obvious thing; I'm not > really happy with its type signature but offhand I can't say how to > generalize it. > > I think this is useful, and if I'm not missing anything (obvious or subtle) > about it, I want to propose that it goes into Data.Dynamic. > > _______________________________________________ > Libraries mailing list > Libraries at haskell.org > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries > From ekmett at gmail.com Wed Dec 27 19:17:36 2017 From: ekmett at gmail.com (Edward Kmett) Date: Wed, 27 Dec 2017 14:17:36 -0500 Subject: Constraint implication In-Reply-To: References: Message-ID: Just a few old observations I've made from implementing these things into type systems of my own: 1.) An internal hom for the category of constraints is admissible: (|-) :: Constraint -> Constraint -> Constraint models entailment, and effectively brings into scope a local rule, but global instance resolution isn't lost if this is only produced from existing instances. To your point, this is analogous to the (:-) :: Constraint -> Constraint -> * external hom for the category of constraints provided by my constraints package, but it is internal, with all of the appropriate CCC operations. 2.) Quantification over constraints is also admissible. Neither one compromises the "thinness" of the category of constraints that provides us global coherence of instance resolution In this case the property that if D is thin, so is [C,D]. forall here can quantify over any other kind you want. Unfortunately, neither implemented in Haskell. You'd need both of them to be able to talk about constraints like (forall a. Eq a |- Eq (f a)). Together could eliminate, morally, the entire Data.Functor.Classes mess. (That said, as implemented those classes are a bit stronger than the quantified form) 3.) Constraint also admits a sum type, (\/) but it acts more like a least upper bound than an either. It is much easier to talk about in the category of constraints using the first part above. Given (p |- r, q |- r), (p \/ q) |- r and vice versa. The key to keeping the category of constraints thin is that you can't case analyze on it, its more like if you look at, say, Ord [a] \/ Eq a you can get to any constraint that you could get to given the intersection of both, not using the particulars of either. e.g. its morally as powerful as Eq [a] in this case. Getting this stuff into GHC is the tricky part! -Edward On Wed, Dec 27, 2017 at 2:50 AM, Ryan Reich wrote: > The Constraint kind appears to lack an interface to an important > capability that is already part of the type checker: constraint > implication. Namely, the ability to provide a witness for the statement > "constraint c1 implies constraint c2" or, more importantly, "for all a, > constraint (c1 a) implies constraint (c2 a)", where c1 and c2 are now > constraint-valued type functions (and possibly even for constraint > functions with multiple parameters). It seems to me that this can follow > the pattern of the "magic" Coercible type class and the (non-magic) > Coercion data type; it provides the programmer with an analogous value to > this example that can be obtained in apparently no other way. > > _______________________________________________ > 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 28 02:16:27 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 27 Dec 2017 21:16:27 -0500 Subject: Proposal: simplify type of ($) Message-ID: Currently, we have something like ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). (a -> b) -> a -> b f $ x = f x And that's only part of the story: GHC has a hack in the type checker to give ($) an impredicative type when fully applied. This allows it to be used when its function argument requires a polymorphic argument. This whole complicated situation could be resolved in a very simple manner: change the type and definition thus. ($) :: a -> a ($) f = f All the type complications go away altogether, and ($) becomes plain Haskell 98. There are only three potential downsides I can think of: 1. The optimizer will see `($) x` as fully applied, which could change its behavior in some cases. There might be circumstances where that is bad. I doubt there will be many. 2. The new type signature may obscure the purpose of the operator to beginners. But based on my experience on StackOverflow, it seems beginners tend to struggle with the idea of ($) anyway; this may not make it much worse. I suspect good Haddocks will help alleviate this concern. 3. Some type family and class instances may not be resolved under certain circumstances which I suspect occur very rarely in practice. class C a where m :: (a -> a) -> () instance C (a -> b) where m _ = () test :: () test = m ($) Today, this compiles with no difficulties; with the proposed change, the user would have to supply a type signature to make it work: test = m (($) :: (a -> b) -> (a -> b)) This can also change when an INCOHERENT instance is selected under similarly contrived circumstances, but those who use such generally deserve what they get. David -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Thu Dec 28 02:27:20 2017 From: david.feuer at gmail.com (David Feuer) Date: Wed, 27 Dec 2017 21:27:20 -0500 Subject: PROPOSAL: Add `disjoint` method to `Data.IntSet` In-Reply-To: References: <9aeac101-bc38-6784-d6df-a32fe5da8349@lopezjuan.com> <1513695714.1051.13.camel@joachim-breitner.de> Message-ID: Would all constructivists actually say so? I'd think there could be some who think that disjoint :: (s, t : Set a) -> x : a -> Either (Not (elem x s)) (Not (elem x t)) in which case being disjoint is a stronger property than just not overlapping. But of course, none of this is really relevant to Haskell. On Dec 19, 2017 6:46 PM, "Andreas Abel" wrote: > I am thinking along the lines of Tikhon. > > Sets "overlap" is a rather uncommon term. [If we were all > constructivists, the situation would be different. Constructively, > "overlap" is certainly the primitive notion, and "disjoint" only its > negation.] > > We can't introduce a positive term for everything. For instance, we all > use > > not . null > > rather than having predicates like "isCons", "inhabited" etc. > > On 19.12.2017 19:01, Tikhon Jelvis wrote: > >> In practice, I hear people talking about "disjoint" sets all the time—it >> comes up a lot more often than "overlapping" or "not overlapping". It might >> have a negative in the name semantically, but it's used as an atomic word >> in practice. (That is, when people say "disjoint" they're *thinking* >> "disjoint" as opposed to "not joint" or "not overlapping".) >> >> I'm in favor of naming functions with common usage in mind, and I think >> "disjoint" is the word people use most often in this context. >> >> On Tue, Dec 19, 2017 at 7:44 AM, Henning Thielemann < >> lemming at henning-thielemann.de > >> wrote: >> >> >> On Tue, 19 Dec 2017, Víctor López Juan wrote: >> >> I'm thinking that `disjoint` is already a negation: >> (dis- (not) + joint (united)). When composing with `not`, the >> user gets >> a double negation `not (disjoint x y)`. There is a then a small >> mental >> effort required to go from "not disjoint" to "overlapping". >> >> If we are going to have only one of the two properties, I would >> rather >> have the positive one (`overlaps`) as primitive. Then `disjoint` >> would >> be written "not (overlaps x y)", which reads quite easily. >> (Or even "not (x `overlaps` y)"). >> >> >> I also dislike double negation and think that 'disjoint' is one. I'd >> prefer to see both 'overlap' and 'disjoint'. >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> >> >> >> >> _______________________________________________ >> Libraries mailing list >> Libraries at haskell.org >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries >> >> > > -- > Andreas Abel <>< Du bist der geliebte Mensch. > > Department of Computer Science and Engineering > Chalmers and Gothenburg University, Sweden > > andreas.abel at gu.se > http://www.cse.chalmers.se/~abela/ > _______________________________________________ > 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 tanuki at gmail.com Thu Dec 28 02:39:54 2017 From: tanuki at gmail.com (Theodore Lief Gannon) Date: Wed, 27 Dec 2017 18:39:54 -0800 Subject: Proposal: simplify type of ($) In-Reply-To: References: Message-ID: So far as pedagogy is concerned, ($) is already one of those things people tend to learn how to use before they really understand the mechanism. And for my part, I think if it were immediately obvious that it's just infix id, it would have helped my early understanding of id! +1 from the peanut gallery. On Dec 27, 2017 6:17 PM, "David Feuer" wrote: > Currently, we have something like > > ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). > (a -> b) -> a -> b > f $ x = f x > > And that's only part of the story: GHC has a hack in the type checker to > give ($) an impredicative type when fully applied. This allows it to be > used when its function argument requires a polymorphic argument. > > This whole complicated situation could be resolved in a very simple > manner: change the type and definition thus. > > ($) :: a -> a > ($) f = f > > All the type complications go away altogether, and ($) becomes plain > Haskell 98. > > There are only three potential downsides I can think of: > > 1. The optimizer will see `($) x` as fully applied, which could change its > behavior in some cases. There might be circumstances where that is bad. I > doubt there will be many. > > 2. The new type signature may obscure the purpose of the operator to > beginners. But based on my experience on StackOverflow, it seems beginners > tend to struggle with the idea of ($) anyway; this may not make it much > worse. I suspect good Haddocks will help alleviate this concern. > > 3. Some type family and class instances may not be resolved under certain > circumstances which I suspect occur very rarely in practice. > > class C a where > m :: (a -> a) -> () > instance C (a -> b) where > m _ = () > test :: () > test = m ($) > > Today, this compiles with no difficulties; with the proposed change, the > user would have to supply a type signature to make it work: > > test = m (($) :: (a -> b) -> (a -> b)) > > This can also change when an INCOHERENT instance is selected under > similarly contrived circumstances, but those who use such generally deserve > what they get. > > 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 ryan.reich at gmail.com Thu Dec 28 07:44:53 2017 From: ryan.reich at gmail.com (Ryan Reich) Date: Wed, 27 Dec 2017 23:44:53 -0800 Subject: Constraint implication In-Reply-To: References: Message-ID: Your 1) is a very erudite way of saying "you forgot about my 'constraints' package" :) Which I did. Although it's just a little more awkward syntactically to write `(a :- b) -> whatever` instead of `(a |- b) => whatever`, which is only possible with a GHC extension, it obviously solves the problem of using constraints of the form `c1 implies c2`, i.e. 0-ary constraint functions. If I understand you correctly, you are saying that an internal entailment operator is consistent with the other workings of constraints, and pointing out the concepts that need to be handled in implementing this in GHC? Re 2): I am probably missing something when I think that `type (c1 :: * -> Constraint) ::- (c2 :: * -> Constraint) = forall a. (c1 a :- c2 a)` works for 1-ary entailment; for instance `Sub Dict :: Ord ::- Eq` appears not to bother ghci. 3) It would be neat, for sure, to have this sum type. Is that the full extent of boolean logic you can define on Constraint without losing thinness? On Wed, Dec 27, 2017 at 11:17 AM, Edward Kmett wrote: > Just a few old observations I've made from implementing these things into > type systems of my own: > > 1.) An internal hom for the category of constraints is admissible: > > (|-) :: Constraint -> Constraint -> Constraint > > models entailment, and effectively brings into scope a local rule, but > global instance resolution isn't lost if this is only produced from > existing instances. > > To your point, this is analogous to the (:-) :: Constraint -> Constraint > -> * external hom for the category of constraints provided by my > constraints package, but it is internal, with all of the appropriate CCC > operations. > > 2.) Quantification over constraints is also admissible. > > Neither one compromises the "thinness" of the category of constraints that > provides us global coherence of instance resolution > > In this case the property that if D is thin, so is [C,D]. forall here can > quantify over any other kind you want. > > Unfortunately, neither implemented in Haskell. > > You'd need both of them to be able to talk about constraints like (forall > a. Eq a |- Eq (f a)). > > Together could eliminate, morally, the entire Data.Functor.Classes mess. > (That said, as implemented those classes are a bit stronger than the > quantified form) > > 3.) Constraint also admits a sum type, (\/) but it acts more like a least > upper bound than an either. > > It is much easier to talk about in the category of constraints using the > first part above. > > Given (p |- r, q |- r), (p \/ q) |- r and vice versa. > > The key to keeping the category of constraints thin is that you can't case > analyze on it, its more like if you look at, say, Ord [a] \/ Eq a you can > get to any constraint that you could get to given the intersection of both, > not using the particulars of either. e.g. its morally as powerful as Eq [a] > in this case. > > Getting this stuff into GHC is the tricky part! > > -Edward > > On Wed, Dec 27, 2017 at 2:50 AM, Ryan Reich wrote: > >> The Constraint kind appears to lack an interface to an important >> capability that is already part of the type checker: constraint >> implication. Namely, the ability to provide a witness for the statement >> "constraint c1 implies constraint c2" or, more importantly, "for all a, >> constraint (c1 a) implies constraint (c2 a)", where c1 and c2 are now >> constraint-valued type functions (and possibly even for constraint >> functions with multiple parameters). It seems to me that this can follow >> the pattern of the "magic" Coercible type class and the (non-magic) >> Coercion data type; it provides the programmer with an analogous value to >> this example that can be obtained in apparently no other way. >> >> _______________________________________________ >> 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 ryan.trinkle at gmail.com Thu Dec 28 13:04:12 2017 From: ryan.trinkle at gmail.com (Ryan Trinkle) Date: Thu, 28 Dec 2017 08:04:12 -0500 Subject: Proposal: simplify type of ($) In-Reply-To: References: Message-ID: Agreed. I've always taught ($) as "a parenthesis that goes as far forward as it can". That seems to be a pretty good heuristic for people to use, and it's a whole lot easier than explaining operator precedence in enough detail that the behavior becomes clear from first principles. On Wed, Dec 27, 2017 at 9:39 PM, Theodore Lief Gannon wrote: > So far as pedagogy is concerned, ($) is already one of those things people > tend to learn how to use before they really understand the mechanism. And > for my part, I think if it were immediately obvious that it's just infix > id, it would have helped my early understanding of id! +1 from the peanut > gallery. > > On Dec 27, 2017 6:17 PM, "David Feuer" wrote: > >> Currently, we have something like >> >> ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). >> (a -> b) -> a -> b >> f $ x = f x >> >> And that's only part of the story: GHC has a hack in the type checker to >> give ($) an impredicative type when fully applied. This allows it to be >> used when its function argument requires a polymorphic argument. >> >> This whole complicated situation could be resolved in a very simple >> manner: change the type and definition thus. >> >> ($) :: a -> a >> ($) f = f >> >> All the type complications go away altogether, and ($) becomes plain >> Haskell 98. >> >> There are only three potential downsides I can think of: >> >> 1. The optimizer will see `($) x` as fully applied, which could change >> its behavior in some cases. There might be circumstances where that is bad. >> I doubt there will be many. >> >> 2. The new type signature may obscure the purpose of the operator to >> beginners. But based on my experience on StackOverflow, it seems beginners >> tend to struggle with the idea of ($) anyway; this may not make it much >> worse. I suspect good Haddocks will help alleviate this concern. >> >> 3. Some type family and class instances may not be resolved under certain >> circumstances which I suspect occur very rarely in practice. >> >> class C a where >> m :: (a -> a) -> () >> instance C (a -> b) where >> m _ = () >> test :: () >> test = m ($) >> >> Today, this compiles with no difficulties; with the proposed change, the >> user would have to supply a type signature to make it work: >> >> test = m (($) :: (a -> b) -> (a -> b)) >> >> This can also change when an INCOHERENT instance is selected under >> similarly contrived circumstances, but those who use such generally deserve >> what they get. >> >> David >> >> _______________________________________________ >> 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 andrew.thaddeus at gmail.com Thu Dec 28 14:56:24 2017 From: andrew.thaddeus at gmail.com (Andrew Martin) Date: Thu, 28 Dec 2017 09:56:24 -0500 Subject: Constraint implication In-Reply-To: References: Message-ID: I agree that this would be cool. Here is some other discussion of this topic: - A research paper proving its soundness: http://i.cs.hku.hk/~bruno/papers/hs2017.pdf - Responses on reddit: https://www.reddit.com/r/haskell/comments/6me3sv/quantified_class_constraints_pdf/ - A very dated GHC issue: https://ghc.haskell.org/trac/ghc/ticket/2893 Many people seem to want this, but to my knowledge, no one has any plans to work on it any time soon. I would not be surprised if it actually ended up getting implemented one day. It could replace everything in Data.Functor.Classes as well as half of the stuff from Data.Exists in my `quantification` package. On Wed, Dec 27, 2017 at 2:50 AM, Ryan Reich wrote: > The Constraint kind appears to lack an interface to an important > capability that is already part of the type checker: constraint > implication. Namely, the ability to provide a witness for the statement > "constraint c1 implies constraint c2" or, more importantly, "for all a, > constraint (c1 a) implies constraint (c2 a)", where c1 and c2 are now > constraint-valued type functions (and possibly even for constraint > functions with multiple parameters). It seems to me that this can follow > the pattern of the "magic" Coercible type class and the (non-magic) > Coercion data type; it provides the programmer with an analogous value to > this example that can be obtained in apparently no other way. > > _______________________________________________ > 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 jeffbrown.the at gmail.com Thu Dec 28 16:57:18 2017 From: jeffbrown.the at gmail.com (Jeffrey Brown) Date: Thu, 28 Dec 2017 11:57:18 -0500 Subject: Proposal: simplify type of ($) In-Reply-To: References: Message-ID: The Wiki says in a few places that Haskell only has one unary operator, negation. those spots would need updating. On Thu, Dec 28, 2017 at 8:04 AM, Ryan Trinkle wrote: > Agreed. I've always taught ($) as "a parenthesis that goes as far forward > as it can". That seems to be a pretty good heuristic for people to use, > and it's a whole lot easier than explaining operator precedence in enough > detail that the behavior becomes clear from first principles. > > On Wed, Dec 27, 2017 at 9:39 PM, Theodore Lief Gannon > wrote: > >> So far as pedagogy is concerned, ($) is already one of those things >> people tend to learn how to use before they really understand the >> mechanism. And for my part, I think if it were immediately obvious that >> it's just infix id, it would have helped my early understanding of id! +1 >> from the peanut gallery. >> >> On Dec 27, 2017 6:17 PM, "David Feuer" wrote: >> >>> Currently, we have something like >>> >>> ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). >>> (a -> b) -> a -> b >>> f $ x = f x >>> >>> And that's only part of the story: GHC has a hack in the type checker to >>> give ($) an impredicative type when fully applied. This allows it to be >>> used when its function argument requires a polymorphic argument. >>> >>> This whole complicated situation could be resolved in a very simple >>> manner: change the type and definition thus. >>> >>> ($) :: a -> a >>> ($) f = f >>> >>> All the type complications go away altogether, and ($) becomes plain >>> Haskell 98. >>> >>> There are only three potential downsides I can think of: >>> >>> 1. The optimizer will see `($) x` as fully applied, which could change >>> its behavior in some cases. There might be circumstances where that is bad. >>> I doubt there will be many. >>> >>> 2. The new type signature may obscure the purpose of the operator to >>> beginners. But based on my experience on StackOverflow, it seems beginners >>> tend to struggle with the idea of ($) anyway; this may not make it much >>> worse. I suspect good Haddocks will help alleviate this concern. >>> >>> 3. Some type family and class instances may not be resolved under >>> certain circumstances which I suspect occur very rarely in practice. >>> >>> class C a where >>> m :: (a -> a) -> () >>> instance C (a -> b) where >>> m _ = () >>> test :: () >>> test = m ($) >>> >>> Today, this compiles with no difficulties; with the proposed change, the >>> user would have to supply a type signature to make it work: >>> >>> test = m (($) :: (a -> b) -> (a -> b)) >>> >>> This can also change when an INCOHERENT instance is selected under >>> similarly contrived circumstances, but those who use such generally deserve >>> what they get. >>> >>> David >>> >>> _______________________________________________ >>> 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 > > -- Jeff Brown | Jeffrey Benjamin Brown Website | Facebook | LinkedIn (spammy, so I often miss messages here) | Github -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.feuer at gmail.com Thu Dec 28 17:59:03 2017 From: david.feuer at gmail.com (David Feuer) Date: Thu, 28 Dec 2017 12:59:03 -0500 Subject: Proposal: simplify type of ($) In-Reply-To: References: Message-ID: It's still a binary operator syntactically. The negation operator is an entirely different kettle of fish. On Dec 28, 2017 11:59 AM, "Jeffrey Brown" wrote: > The Wiki says in a few places that Haskell only has one unary operator, > negation. those spots would need updating. > > On Thu, Dec 28, 2017 at 8:04 AM, Ryan Trinkle > wrote: > >> Agreed. I've always taught ($) as "a parenthesis that goes as far >> forward as it can". That seems to be a pretty good heuristic for people to >> use, and it's a whole lot easier than explaining operator precedence in >> enough detail that the behavior becomes clear from first principles. >> >> On Wed, Dec 27, 2017 at 9:39 PM, Theodore Lief Gannon >> wrote: >> >>> So far as pedagogy is concerned, ($) is already one of those things >>> people tend to learn how to use before they really understand the >>> mechanism. And for my part, I think if it were immediately obvious that >>> it's just infix id, it would have helped my early understanding of id! +1 >>> from the peanut gallery. >>> >>> On Dec 27, 2017 6:17 PM, "David Feuer" wrote: >>> >>>> Currently, we have something like >>>> >>>> ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). >>>> (a -> b) -> a -> b >>>> f $ x = f x >>>> >>>> And that's only part of the story: GHC has a hack in the type checker >>>> to give ($) an impredicative type when fully applied. This allows it to be >>>> used when its function argument requires a polymorphic argument. >>>> >>>> This whole complicated situation could be resolved in a very simple >>>> manner: change the type and definition thus. >>>> >>>> ($) :: a -> a >>>> ($) f = f >>>> >>>> All the type complications go away altogether, and ($) becomes plain >>>> Haskell 98. >>>> >>>> There are only three potential downsides I can think of: >>>> >>>> 1. The optimizer will see `($) x` as fully applied, which could change >>>> its behavior in some cases. There might be circumstances where that is bad. >>>> I doubt there will be many. >>>> >>>> 2. The new type signature may obscure the purpose of the operator to >>>> beginners. But based on my experience on StackOverflow, it seems beginners >>>> tend to struggle with the idea of ($) anyway; this may not make it much >>>> worse. I suspect good Haddocks will help alleviate this concern. >>>> >>>> 3. Some type family and class instances may not be resolved under >>>> certain circumstances which I suspect occur very rarely in practice. >>>> >>>> class C a where >>>> m :: (a -> a) -> () >>>> instance C (a -> b) where >>>> m _ = () >>>> test :: () >>>> test = m ($) >>>> >>>> Today, this compiles with no difficulties; with the proposed change, >>>> the user would have to supply a type signature to make it work: >>>> >>>> test = m (($) :: (a -> b) -> (a -> b)) >>>> >>>> This can also change when an INCOHERENT instance is selected under >>>> similarly contrived circumstances, but those who use such generally deserve >>>> what they get. >>>> >>>> David >>>> >>>> _______________________________________________ >>>> 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 >> >> > > > -- > Jeff Brown | Jeffrey Benjamin Brown > Website | Facebook > | LinkedIn > (spammy, so I often > miss messages here) | Github > > > _______________________________________________ > 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 ekmett at gmail.com Thu Dec 28 22:19:03 2017 From: ekmett at gmail.com (Edward Kmett) Date: Thu, 28 Dec 2017 17:19:03 -0500 Subject: Constraint implication In-Reply-To: References: Message-ID: On Thu, Dec 28, 2017 at 2:44 AM, Ryan Reich wrote: > Your 1) is a very erudite way of saying "you forgot about my 'constraints' > package" :) Which I did. > Not exactly. The constraints package can construct (:-) :: Constraint -> Constraint -> * but (|-) :: Constraint -> Constraint -> Constraint would really need compiler support to work correctly. That said, it might be able to be written as a GHC plugin, now that I think about it. (3) could also most likely be handled that way. > Although it's just a little more awkward syntactically to write `(a :- b) > -> whatever` instead of `(a |- b) => whatever`, which is only possible with > a GHC extension, it obviously solves the problem of using constraints of > the form `c1 implies c2`, i.e. 0-ary constraint functions. If I understand > you correctly, you are saying that an internal entailment operator is > consistent with the other workings of constraints, and pointing out the > concepts that need to be handled in implementing this in GHC? > Yep. > Re 2): I am probably missing something when I think that `type (c1 :: * -> > Constraint) ::- (c2 :: * -> Constraint) = forall a. (c1 a :- c2 a)` works > for 1-ary entailment; for instance `Sub Dict :: Ord ::- Eq` appears not to > bother ghci. > data Jet f a = a :- Jet f (f a) is an example of a data type for which show, (==), compare, etc. are a pain in the neck to write. For that you really want something like instance (Ord a, forall x. Ord x |- Ord (f x)) => Ord (Jet f a) In the constraints vocabulary today this particular usecase can sort of be faked by using Lifting: instance (Lifting Ord f, Ord a) => Ord (Jet f a) but GHC doesn't know enough to automatically bring the right stuff into scope to make it automatically work, you have to write a crapload of manual Lifting instances you might not expect, and you have to open the dictionary from Lifting by hand, and its generally a mess to use. 3) It would be neat, for sure, to have this sum type. Is that the full > extent of boolean logic you can define on Constraint without losing > thinness? > Technically it is a Heyting algebra. You can go a bit crazier with the type theory for the category of constraints and show that its locally cartesian closed, which seems to admit some funny interpretations of MLTT in it as well. -Edward On Wed, Dec 27, 2017 at 11:17 AM, Edward Kmett wrote: > >> Just a few old observations I've made from implementing these things into >> type systems of my own: >> >> 1.) An internal hom for the category of constraints is admissible: >> >> (|-) :: Constraint -> Constraint -> Constraint >> >> models entailment, and effectively brings into scope a local rule, but >> global instance resolution isn't lost if this is only produced from >> existing instances. >> >> To your point, this is analogous to the (:-) :: Constraint -> Constraint >> -> * external hom for the category of constraints provided by my >> constraints package, but it is internal, with all of the appropriate CCC >> operations. >> >> 2.) Quantification over constraints is also admissible. >> >> Neither one compromises the "thinness" of the category of constraints >> that provides us global coherence of instance resolution >> >> In this case the property that if D is thin, so is [C,D]. forall here can >> quantify over any other kind you want. >> >> Unfortunately, neither implemented in Haskell. >> >> You'd need both of them to be able to talk about constraints like (forall >> a. Eq a |- Eq (f a)). >> >> Together could eliminate, morally, the entire Data.Functor.Classes mess. >> (That said, as implemented those classes are a bit stronger than the >> quantified form) >> >> 3.) Constraint also admits a sum type, (\/) but it acts more like a least >> upper bound than an either. >> >> It is much easier to talk about in the category of constraints using the >> first part above. >> >> Given (p |- r, q |- r), (p \/ q) |- r and vice versa. >> >> The key to keeping the category of constraints thin is that you can't >> case analyze on it, its more like if you look at, say, Ord [a] \/ Eq a you >> can get to any constraint that you could get to given the intersection of >> both, not using the particulars of either. e.g. its morally as powerful as >> Eq [a] in this case. >> >> Getting this stuff into GHC is the tricky part! >> >> -Edward >> >> On Wed, Dec 27, 2017 at 2:50 AM, Ryan Reich wrote: >> >>> The Constraint kind appears to lack an interface to an important >>> capability that is already part of the type checker: constraint >>> implication. Namely, the ability to provide a witness for the statement >>> "constraint c1 implies constraint c2" or, more importantly, "for all a, >>> constraint (c1 a) implies constraint (c2 a)", where c1 and c2 are now >>> constraint-valued type functions (and possibly even for constraint >>> functions with multiple parameters). It seems to me that this can follow >>> the pattern of the "magic" Coercible type class and the (non-magic) >>> Coercion data type; it provides the programmer with an analogous value to >>> this example that can be obtained in apparently no other way. >>> >>> _______________________________________________ >>> 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 ekmett at gmail.com Thu Dec 28 22:26:40 2017 From: ekmett at gmail.com (Edward Kmett) Date: Thu, 28 Dec 2017 17:26:40 -0500 Subject: Proposal: simplify type of ($) In-Reply-To: References: Message-ID: This doesn't seem to eliminate the need for the GHC type checking hack. You still have to instantiate the type of the single argument to ($) with a polytype to typecheck the usual runST $ do ... idiom. Prelude Control.Monad.ST> runST $ pure () () Prelude Control.Monad.ST> let ($) a = a Prelude Control.Monad.ST> runST $ pure () *:4:1: **error:* * • Couldn't match type ‘forall s. ST s t’ with ‘f0 ()’* * Expected type: f0 () -> t* * Actual type: (forall s. ST s t) -> t* * • In the first argument of ‘($)’, namely ‘runST’* * In the expression: runST $ pure ()* * In an equation for ‘it’: it = runST $ pure ()* * • Relevant bindings include it :: t (bound at :4:1)* -Edward On Thu, Dec 28, 2017 at 12:59 PM, David Feuer wrote: > It's still a binary operator syntactically. The negation operator is an > entirely different kettle of fish. > > On Dec 28, 2017 11:59 AM, "Jeffrey Brown" wrote: > >> The Wiki says in a few places that Haskell only has one unary operator, >> negation. those spots would need updating. >> >> On Thu, Dec 28, 2017 at 8:04 AM, Ryan Trinkle >> wrote: >> >>> Agreed. I've always taught ($) as "a parenthesis that goes as far >>> forward as it can". That seems to be a pretty good heuristic for people to >>> use, and it's a whole lot easier than explaining operator precedence in >>> enough detail that the behavior becomes clear from first principles. >>> >>> On Wed, Dec 27, 2017 at 9:39 PM, Theodore Lief Gannon >>> wrote: >>> >>>> So far as pedagogy is concerned, ($) is already one of those things >>>> people tend to learn how to use before they really understand the >>>> mechanism. And for my part, I think if it were immediately obvious that >>>> it's just infix id, it would have helped my early understanding of id! +1 >>>> from the peanut gallery. >>>> >>>> On Dec 27, 2017 6:17 PM, "David Feuer" wrote: >>>> >>>>> Currently, we have something like >>>>> >>>>> ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). >>>>> (a -> b) -> a -> b >>>>> f $ x = f x >>>>> >>>>> And that's only part of the story: GHC has a hack in the type checker >>>>> to give ($) an impredicative type when fully applied. This allows it to be >>>>> used when its function argument requires a polymorphic argument. >>>>> >>>>> This whole complicated situation could be resolved in a very simple >>>>> manner: change the type and definition thus. >>>>> >>>>> ($) :: a -> a >>>>> ($) f = f >>>>> >>>>> All the type complications go away altogether, and ($) becomes plain >>>>> Haskell 98. >>>>> >>>>> There are only three potential downsides I can think of: >>>>> >>>>> 1. The optimizer will see `($) x` as fully applied, which could change >>>>> its behavior in some cases. There might be circumstances where that is bad. >>>>> I doubt there will be many. >>>>> >>>>> 2. The new type signature may obscure the purpose of the operator to >>>>> beginners. But based on my experience on StackOverflow, it seems beginners >>>>> tend to struggle with the idea of ($) anyway; this may not make it much >>>>> worse. I suspect good Haddocks will help alleviate this concern. >>>>> >>>>> 3. Some type family and class instances may not be resolved under >>>>> certain circumstances which I suspect occur very rarely in practice. >>>>> >>>>> class C a where >>>>> m :: (a -> a) -> () >>>>> instance C (a -> b) where >>>>> m _ = () >>>>> test :: () >>>>> test = m ($) >>>>> >>>>> Today, this compiles with no difficulties; with the proposed change, >>>>> the user would have to supply a type signature to make it work: >>>>> >>>>> test = m (($) :: (a -> b) -> (a -> b)) >>>>> >>>>> This can also change when an INCOHERENT instance is selected under >>>>> similarly contrived circumstances, but those who use such generally deserve >>>>> what they get. >>>>> >>>>> David >>>>> >>>>> _______________________________________________ >>>>> 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 >>> >>> >> >> >> -- >> Jeff Brown | Jeffrey Benjamin Brown >> Website | Facebook >> | LinkedIn >> (spammy, so I often >> miss messages here) | Github >> >> >> _______________________________________________ >> 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 Thu Dec 28 22:34:28 2017 From: david.feuer at gmail.com (David Feuer) Date: Thu, 28 Dec 2017 17:34:28 -0500 Subject: Proposal: simplify type of ($) In-Reply-To: References: Message-ID: Blast! I thought I'd checked that. It eliminates the representation polymorphism, but not the impredicativitu issue. Oops. Still seems like a simplification. On Dec 28, 2017 5:26 PM, "Edward Kmett" wrote: > This doesn't seem to eliminate the need for the GHC type checking hack. > > You still have to instantiate the type of the single argument to ($) with > a polytype to typecheck the usual runST $ do ... idiom. > > Prelude Control.Monad.ST> runST $ pure () > > () > > Prelude Control.Monad.ST> let ($) a = a > > Prelude Control.Monad.ST> runST $ pure () > > > *:4:1: **error:* > > * • Couldn't match type ‘forall s. ST s t’ with ‘f0 ()’* > > * Expected type: f0 () -> t* > > * Actual type: (forall s. ST s t) -> t* > > * • In the first argument of ‘($)’, namely ‘runST’* > > * In the expression: runST $ pure ()* > > * In an equation for ‘it’: it = runST $ pure ()* > > * • Relevant bindings include it :: t (bound at :4:1)* > > > > -Edward > > On Thu, Dec 28, 2017 at 12:59 PM, David Feuer > wrote: > >> It's still a binary operator syntactically. The negation operator is an >> entirely different kettle of fish. >> >> On Dec 28, 2017 11:59 AM, "Jeffrey Brown" >> wrote: >> >>> The Wiki says in a few places that Haskell only has one unary operator, >>> negation. those spots would need updating. >>> >>> On Thu, Dec 28, 2017 at 8:04 AM, Ryan Trinkle >>> wrote: >>> >>>> Agreed. I've always taught ($) as "a parenthesis that goes as far >>>> forward as it can". That seems to be a pretty good heuristic for people to >>>> use, and it's a whole lot easier than explaining operator precedence in >>>> enough detail that the behavior becomes clear from first principles. >>>> >>>> On Wed, Dec 27, 2017 at 9:39 PM, Theodore Lief Gannon >>> > wrote: >>>> >>>>> So far as pedagogy is concerned, ($) is already one of those things >>>>> people tend to learn how to use before they really understand the >>>>> mechanism. And for my part, I think if it were immediately obvious that >>>>> it's just infix id, it would have helped my early understanding of id! +1 >>>>> from the peanut gallery. >>>>> >>>>> On Dec 27, 2017 6:17 PM, "David Feuer" wrote: >>>>> >>>>>> Currently, we have something like >>>>>> >>>>>> ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). >>>>>> (a -> b) -> a -> b >>>>>> f $ x = f x >>>>>> >>>>>> And that's only part of the story: GHC has a hack in the type checker >>>>>> to give ($) an impredicative type when fully applied. This allows it to be >>>>>> used when its function argument requires a polymorphic argument. >>>>>> >>>>>> This whole complicated situation could be resolved in a very simple >>>>>> manner: change the type and definition thus. >>>>>> >>>>>> ($) :: a -> a >>>>>> ($) f = f >>>>>> >>>>>> All the type complications go away altogether, and ($) becomes plain >>>>>> Haskell 98. >>>>>> >>>>>> There are only three potential downsides I can think of: >>>>>> >>>>>> 1. The optimizer will see `($) x` as fully applied, which could >>>>>> change its behavior in some cases. There might be circumstances where that >>>>>> is bad. I doubt there will be many. >>>>>> >>>>>> 2. The new type signature may obscure the purpose of the operator to >>>>>> beginners. But based on my experience on StackOverflow, it seems beginners >>>>>> tend to struggle with the idea of ($) anyway; this may not make it much >>>>>> worse. I suspect good Haddocks will help alleviate this concern. >>>>>> >>>>>> 3. Some type family and class instances may not be resolved under >>>>>> certain circumstances which I suspect occur very rarely in practice. >>>>>> >>>>>> class C a where >>>>>> m :: (a -> a) -> () >>>>>> instance C (a -> b) where >>>>>> m _ = () >>>>>> test :: () >>>>>> test = m ($) >>>>>> >>>>>> Today, this compiles with no difficulties; with the proposed change, >>>>>> the user would have to supply a type signature to make it work: >>>>>> >>>>>> test = m (($) :: (a -> b) -> (a -> b)) >>>>>> >>>>>> This can also change when an INCOHERENT instance is selected under >>>>>> similarly contrived circumstances, but those who use such generally deserve >>>>>> what they get. >>>>>> >>>>>> David >>>>>> >>>>>> _______________________________________________ >>>>>> 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 >>>> >>>> >>> >>> >>> -- >>> Jeff Brown | Jeffrey Benjamin Brown >>> Website | Facebook >>> | LinkedIn >>> (spammy, so I often >>> miss messages here) | Github >>> >>> >>> _______________________________________________ >>> 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 Thu Dec 28 23:40:16 2017 From: david.feuer at gmail.com (David Feuer) Date: Thu, 28 Dec 2017 18:40:16 -0500 Subject: Proposal: simplify type of ($) In-Reply-To: References: Message-ID: I am curious about one thing, though. With the single-argument ($), the type problem is that we need to instantiate a type variable to a type like (forall s. ST s t) -> t. The type quantification there is wrapped up under the arrow, rather than being exposed (as it would be in the second argument of a two-argument ($)). Would allowing such instantiations cause as much trouble for type inference as general impredicative types? On Thu, Dec 28, 2017 at 5:26 PM, Edward Kmett wrote: > This doesn't seem to eliminate the need for the GHC type checking hack. > > You still have to instantiate the type of the single argument to ($) with a > polytype to typecheck the usual runST $ do ... idiom. > > Prelude Control.Monad.ST> runST $ pure () > > () > > Prelude Control.Monad.ST> let ($) a = a > > Prelude Control.Monad.ST> runST $ pure () > > > :4:1: error: > > • Couldn't match type ‘forall s. ST s t’ with ‘f0 ()’ > > Expected type: f0 () -> t > > Actual type: (forall s. ST s t) -> t > > • In the first argument of ‘($)’, namely ‘runST’ > > In the expression: runST $ pure () > > In an equation for ‘it’: it = runST $ pure () > > • Relevant bindings include it :: t (bound at :4:1) > > > > -Edward > > On Thu, Dec 28, 2017 at 12:59 PM, David Feuer wrote: >> >> It's still a binary operator syntactically. The negation operator is an >> entirely different kettle of fish. >> >> On Dec 28, 2017 11:59 AM, "Jeffrey Brown" wrote: >>> >>> The Wiki says in a few places that Haskell only has one unary operator, >>> negation. those spots would need updating. >>> >>> On Thu, Dec 28, 2017 at 8:04 AM, Ryan Trinkle >>> wrote: >>>> >>>> Agreed. I've always taught ($) as "a parenthesis that goes as far >>>> forward as it can". That seems to be a pretty good heuristic for people to >>>> use, and it's a whole lot easier than explaining operator precedence in >>>> enough detail that the behavior becomes clear from first principles. >>>> >>>> On Wed, Dec 27, 2017 at 9:39 PM, Theodore Lief Gannon >>>> wrote: >>>>> >>>>> So far as pedagogy is concerned, ($) is already one of those things >>>>> people tend to learn how to use before they really understand the mechanism. >>>>> And for my part, I think if it were immediately obvious that it's just infix >>>>> id, it would have helped my early understanding of id! +1 from the peanut >>>>> gallery. >>>>> >>>>> On Dec 27, 2017 6:17 PM, "David Feuer" wrote: >>>>>> >>>>>> Currently, we have something like >>>>>> >>>>>> ($) :: forall r1 r2 (a :: TYPE r1) (b :: TYPE r2). >>>>>> (a -> b) -> a -> b >>>>>> f $ x = f x >>>>>> >>>>>> And that's only part of the story: GHC has a hack in the type checker >>>>>> to give ($) an impredicative type when fully applied. This allows it to be >>>>>> used when its function argument requires a polymorphic argument. >>>>>> >>>>>> This whole complicated situation could be resolved in a very simple >>>>>> manner: change the type and definition thus. >>>>>> >>>>>> ($) :: a -> a >>>>>> ($) f = f >>>>>> >>>>>> All the type complications go away altogether, and ($) becomes plain >>>>>> Haskell 98. >>>>>> >>>>>> There are only three potential downsides I can think of: >>>>>> >>>>>> 1. The optimizer will see `($) x` as fully applied, which could change >>>>>> its behavior in some cases. There might be circumstances where that is bad. >>>>>> I doubt there will be many. >>>>>> >>>>>> 2. The new type signature may obscure the purpose of the operator to >>>>>> beginners. But based on my experience on StackOverflow, it seems beginners >>>>>> tend to struggle with the idea of ($) anyway; this may not make it much >>>>>> worse. I suspect good Haddocks will help alleviate this concern. >>>>>> >>>>>> 3. Some type family and class instances may not be resolved under >>>>>> certain circumstances which I suspect occur very rarely in practice. >>>>>> >>>>>> class C a where >>>>>> m :: (a -> a) -> () >>>>>> instance C (a -> b) where >>>>>> m _ = () >>>>>> test :: () >>>>>> test = m ($) >>>>>> >>>>>> Today, this compiles with no difficulties; with the proposed change, >>>>>> the user would have to supply a type signature to make it work: >>>>>> >>>>>> test = m (($) :: (a -> b) -> (a -> b)) >>>>>> >>>>>> This can also change when an INCOHERENT instance is selected under >>>>>> similarly contrived circumstances, but those who use such generally deserve >>>>>> what they get. >>>>>> >>>>>> David >>>>>> >>>>>> _______________________________________________ >>>>>> 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 >>>> >>> >>> >>> >>> -- >>> Jeff Brown | Jeffrey Benjamin Brown >>> Website | Facebook | LinkedIn(spammy, so I often miss messages >>> here) | Github >>> >>> _______________________________________________ >>> 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 rae at cs.brynmawr.edu Fri Dec 29 15:25:26 2017 From: rae at cs.brynmawr.edu (Richard Eisenberg) Date: Fri, 29 Dec 2017 10:25:26 -0500 Subject: add a new equation to Data.Type.Bool.If Message-ID: <19D70F36-E4AB-47DA-9351-69E7A7624727@cs.brynmawr.edu> Currently, we have (in Data.Type.Bool): > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ > type family If cond tru fls where > If 'True tru fls = tru > If 'False tru fls = fls I propose adding a new equation, thus: > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ > type family If cond tru fls where > If b same same = same > If 'True tru fls = tru > If 'False tru fls = fls This new equation would allow If to reduce when we don't know the condition but we do know that both branches are the same. All three equations are *compatible* (a technical term defined in the closed type families paper), meaning that GHC ignores the ordering between them and will just choose whichever equation matches. Any objections? Thanks, Richard From david.feuer at gmail.com Fri Dec 29 15:34:13 2017 From: david.feuer at gmail.com (David Feuer) Date: Fri, 29 Dec 2017 10:34:13 -0500 Subject: add a new equation to Data.Type.Bool.If In-Reply-To: <19D70F36-E4AB-47DA-9351-69E7A7624727@cs.brynmawr.edu> References: <19D70F36-E4AB-47DA-9351-69E7A7624727@cs.brynmawr.edu> Message-ID: Heh. I already wrote the Phab differential weeks ago. But then I noticed there's room for more equations, and wasn't sure where to stop. If x x False = x If x True False = x If x True x = x On Dec 29, 2017 10:27 AM, "Richard Eisenberg" wrote: > Currently, we have (in Data.Type.Bool): > > > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ > > type family If cond tru fls where > > If 'True tru fls = tru > > If 'False tru fls = fls > > I propose adding a new equation, thus: > > > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ > > type family If cond tru fls where > > If b same same = same > > If 'True tru fls = tru > > If 'False tru fls = fls > > This new equation would allow If to reduce when we don't know the > condition but we do know that both branches are the same. All three > equations are *compatible* (a technical term defined in the closed type > families paper), meaning that GHC ignores the ordering between them and > will just choose whichever equation matches. > > Any objections? > > Thanks, > Richard > _______________________________________________ > 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 ekmett at gmail.com Fri Dec 29 17:27:20 2017 From: ekmett at gmail.com (Edward Kmett) Date: Fri, 29 Dec 2017 12:27:20 -0500 Subject: add a new equation to Data.Type.Bool.If In-Reply-To: References: <19D70F36-E4AB-47DA-9351-69E7A7624727@cs.brynmawr.edu> Message-ID: If you want a laundry list, there's an exhaustive set of normal forms in 'normalized' here: https://github.com/ekmett/coda/blob/b278ceab217236f24a26e22a459d4455addd40db/lib/bdd/Data/BDD.hs#L266\ which is used to shrink the size of my 'if-then-else' lookup tables for BDDs. You don't need the normal forms per se, (and getting them requires some notion of ordering we can't offer), but you may find those and the base cases at https://github.com/ekmett/coda/blob/b278ceab217236f24a26e22a459d4455addd40db/lib/bdd/Data/BDD.hs#L313 to be useful at reducing the amount of stuff you need to compute. -Edward On Fri, Dec 29, 2017 at 10:34 AM, David Feuer wrote: > Heh. I already wrote the Phab differential weeks ago. But then I noticed > there's room for more equations, and wasn't sure where to stop. > > If x x False = x > If x True False = x > If x True x = x > > On Dec 29, 2017 10:27 AM, "Richard Eisenberg" wrote: > >> Currently, we have (in Data.Type.Bool): >> >> > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ >> > type family If cond tru fls where >> > If 'True tru fls = tru >> > If 'False tru fls = fls >> >> I propose adding a new equation, thus: >> >> > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ >> > type family If cond tru fls where >> > If b same same = same >> > If 'True tru fls = tru >> > If 'False tru fls = fls >> >> This new equation would allow If to reduce when we don't know the >> condition but we do know that both branches are the same. All three >> equations are *compatible* (a technical term defined in the closed type >> families paper), meaning that GHC ignores the ordering between them and >> will just choose whichever equation matches. >> >> Any objections? >> >> Thanks, >> Richard >> _______________________________________________ >> 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 Fri Dec 29 18:38:44 2017 From: david.feuer at gmail.com (David Feuer) Date: Fri, 29 Dec 2017 13:38:44 -0500 Subject: add a new equation to Data.Type.Bool.If In-Reply-To: References: <19D70F36-E4AB-47DA-9351-69E7A7624727@cs.brynmawr.edu> Message-ID: Well, the tricky thing is that we have lots of extra ones. For instance, If x (f 'True) (f 'False) = f x If x (g 'True a) (g 'False a) = g x a If x (g 'True 'True) (g 'False 'False) = g x x On Dec 29, 2017 12:27 PM, "Edward Kmett" wrote: > If you want a laundry list, there's an exhaustive set of normal forms in > 'normalized' here: https://github.com/ekmett/coda/blob/ > b278ceab217236f24a26e22a459d4455addd40db/lib/bdd/Data/BDD.hs#L266\ > > which is used to shrink the size of my 'if-then-else' lookup tables for > BDDs. > > You don't need the normal forms per se, (and getting them requires some > notion of ordering we can't offer), but you may find those and the base > cases at > https://github.com/ekmett/coda/blob/b278ceab217236f24a26e22a459d44 > 55addd40db/lib/bdd/Data/BDD.hs#L313 > to be useful at reducing the amount of stuff you need to compute. > > -Edward > > On Fri, Dec 29, 2017 at 10:34 AM, David Feuer > wrote: > >> Heh. I already wrote the Phab differential weeks ago. But then I noticed >> there's room for more equations, and wasn't sure where to stop. >> >> If x x False = x >> If x True False = x >> If x True x = x >> >> On Dec 29, 2017 10:27 AM, "Richard Eisenberg" >> wrote: >> >>> Currently, we have (in Data.Type.Bool): >>> >>> > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ >>> > type family If cond tru fls where >>> > If 'True tru fls = tru >>> > If 'False tru fls = fls >>> >>> I propose adding a new equation, thus: >>> >>> > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ >>> > type family If cond tru fls where >>> > If b same same = same >>> > If 'True tru fls = tru >>> > If 'False tru fls = fls >>> >>> This new equation would allow If to reduce when we don't know the >>> condition but we do know that both branches are the same. All three >>> equations are *compatible* (a technical term defined in the closed type >>> families paper), meaning that GHC ignores the ordering between them and >>> will just choose whichever equation matches. >>> >>> Any objections? >>> >>> Thanks, >>> Richard >>> _______________________________________________ >>> 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 rae at cs.brynmawr.edu Fri Dec 29 21:20:28 2017 From: rae at cs.brynmawr.edu (Richard Eisenberg) Date: Fri, 29 Dec 2017 16:20:28 -0500 Subject: add a new equation to Data.Type.Bool.If In-Reply-To: References: <19D70F36-E4AB-47DA-9351-69E7A7624727@cs.brynmawr.edu> Message-ID: <2BC30409-D352-4EBF-81F0-0AA119A436DA@cs.brynmawr.edu> All of these require some knowledge of k, the kind of the branches. My new equation does not. Now, there's not necessarily a principled reason why we should do one and not the other, but at least we can argue that there is a difference. Nevertheless, I see your point here and recognize that it may be best to leave things as they are. Richard > On Dec 29, 2017, at 1:38 PM, David Feuer wrote: > > Well, the tricky thing is that we have lots of extra ones. For instance, > > If x (f 'True) (f 'False) = f x > If x (g 'True a) (g 'False a) = g x a > If x (g 'True 'True) (g 'False 'False) = g x x > > On Dec 29, 2017 12:27 PM, "Edward Kmett" > wrote: > If you want a laundry list, there's an exhaustive set of normal forms in 'normalized' here: https://github.com/ekmett/coda/blob/b278ceab217236f24a26e22a459d4455addd40db/lib/bdd/Data/BDD.hs#L266\ > > which is used to shrink the size of my 'if-then-else' lookup tables for BDDs. > > You don't need the normal forms per se, (and getting them requires some notion of ordering we can't offer), but you may find those and the base cases at > https://github.com/ekmett/coda/blob/b278ceab217236f24a26e22a459d4455addd40db/lib/bdd/Data/BDD.hs#L313 > to be useful at reducing the amount of stuff you need to compute. > > -Edward > > On Fri, Dec 29, 2017 at 10:34 AM, David Feuer > wrote: > Heh. I already wrote the Phab differential weeks ago. But then I noticed there's room for more equations, and wasn't sure where to stop. > > If x x False = x > If x True False = x > If x True x = x > > On Dec 29, 2017 10:27 AM, "Richard Eisenberg" > wrote: > Currently, we have (in Data.Type.Bool): > > > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ > > type family If cond tru fls where > > If 'True tru fls = tru > > If 'False tru fls = fls > > I propose adding a new equation, thus: > > > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ > > type family If cond tru fls where > > If b same same = same > > If 'True tru fls = tru > > If 'False tru fls = fls > > This new equation would allow If to reduce when we don't know the condition but we do know that both branches are the same. All three equations are *compatible* (a technical term defined in the closed type families paper), meaning that GHC ignores the ordering between them and will just choose whichever equation matches. > > Any objections? > > Thanks, > Richard > _______________________________________________ > 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 Fri Dec 29 21:36:35 2017 From: david.feuer at gmail.com (David Feuer) Date: Fri, 29 Dec 2017 16:36:35 -0500 Subject: add a new equation to Data.Type.Bool.If In-Reply-To: <2BC30409-D352-4EBF-81F0-0AA119A436DA@cs.brynmawr.edu> References: <19D70F36-E4AB-47DA-9351-69E7A7624727@cs.brynmawr.edu> <2BC30409-D352-4EBF-81F0-0AA119A436DA@cs.brynmawr.edu> Message-ID: Oh, I have no objection whatsoever to extension! We just have to decide where to draw the line. The place you've picked certainly doesn't seem unreasonable, and really seems like the least we should do. Pushing further to Bool -> Bool -> Bool -> Bool specials also seems potentially reasonable, to improve interaction with &&, ||, and Not. On Dec 29, 2017 4:20 PM, "Richard Eisenberg" wrote: > All of these require some knowledge of k, the kind of the branches. My new > equation does not. Now, there's not necessarily a principled reason why we > should do one and not the other, but at least we can argue that there is a > difference. > > Nevertheless, I see your point here and recognize that it may be best to > leave things as they are. > > Richard > > On Dec 29, 2017, at 1:38 PM, David Feuer wrote: > > Well, the tricky thing is that we have lots of extra ones. For instance, > > If x (f 'True) (f 'False) = f x > If x (g 'True a) (g 'False a) = g x a > If x (g 'True 'True) (g 'False 'False) = g x x > > On Dec 29, 2017 12:27 PM, "Edward Kmett" wrote: > >> If you want a laundry list, there's an exhaustive set of normal forms in >> 'normalized' here: https://github.com/ekmett/coda >> /blob/b278ceab217236f24a26e22a459d4455addd40db/lib/bdd/Data/BDD.hs#L266\ >> >> which is used to shrink the size of my 'if-then-else' lookup tables for >> BDDs. >> >> You don't need the normal forms per se, (and getting them requires some >> notion of ordering we can't offer), but you may find those and the base >> cases at >> https://github.com/ekmett/coda/blob/b278ceab217236f24a26e22a >> 459d4455addd40db/lib/bdd/Data/BDD.hs#L313 >> to be useful at reducing the amount of stuff you need to compute. >> >> -Edward >> >> On Fri, Dec 29, 2017 at 10:34 AM, David Feuer >> wrote: >> >>> Heh. I already wrote the Phab differential weeks ago. But then I noticed >>> there's room for more equations, and wasn't sure where to stop. >>> >>> If x x False = x >>> If x True False = x >>> If x True x = x >>> >>> On Dec 29, 2017 10:27 AM, "Richard Eisenberg" >>> wrote: >>> >>>> Currently, we have (in Data.Type.Bool): >>>> >>>> > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ >>>> > type family If cond tru fls where >>>> > If 'True tru fls = tru >>>> > If 'False tru fls = fls >>>> >>>> I propose adding a new equation, thus: >>>> >>>> > -- | Type-level "If". @If True a b@ ==> @a@; @If False a b@ ==> @b@ >>>> > type family If cond tru fls where >>>> > If b same same = same >>>> > If 'True tru fls = tru >>>> > If 'False tru fls = fls >>>> >>>> This new equation would allow If to reduce when we don't know the >>>> condition but we do know that both branches are the same. All three >>>> equations are *compatible* (a technical term defined in the closed type >>>> families paper), meaning that GHC ignores the ordering between them and >>>> will just choose whichever equation matches. >>>> >>>> Any objections? >>>> >>>> Thanks, >>>> Richard >>>> _______________________________________________ >>>> 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: