Deprecate Foldable for Either
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`. With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed. I think this instance is harmful and should be deprecated (and later removed) from base. There are similarly pointless Foldable instances as well. See a discussion one year ago, which was heated, but had no consequences. https://mail.haskell.org/pipermail/libraries/2016-February/026678.html -- Andreas Abel <>< Du bist der geliebte Mensch. Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden andreas.abel@gu.se http://www.cse.chalmers.se/~abela/
On Thu, 2 Mar 2017, Andreas Abel wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
That is, he did (concat (xs :: [Either a [b]]))? Does GHC actually accept that? If at all, it would not have to do with Foldable.
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad. On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se http://www.cse.chalmers.se/~abela/ _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Another type can be added to base which does have the Traversable instance. On Thu, Mar 2, 2017 at 4:48 PM, David Feuer <david.feuer@gmail.com> wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se http://www.cse.chalmers.se/~abela/ _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea." On 02.03.2017 17:48, David Feuer wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/026678.html>
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se <mailto:andreas.abel@gu.se> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se http://www.cse.chalmers.se/~abela/
On Thu, Mar 02, 2017 at 05:59:18PM +0100, Andreas Abel wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
I don't fancy Foldable for Either either, but runtime failures are ugly too.
Personally, I think it would be a shame to lose foldMap on EIther. I frequently foldMap over Maybe values (where mempty is suitable in case of "failure"), and I can certainly see myself doing the same thing with Either. - ocharles On Thu, Mar 2, 2017 at 5:08 PM Francesco Ariis <fa-ml@ariis.it> wrote:
On Thu, Mar 02, 2017 at 05:59:18PM +0100, Andreas Abel wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
I don't fancy Foldable for Either either, but runtime failures are ugly too.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
On Thu, Mar 02, 2017 at 05:19:26PM +0000, Oliver Charles wrote:
Personally, I think it would be a shame to lose foldMap on EIther. I frequently foldMap over Maybe values (where mempty is suitable in case of "failure"), and I can certainly see myself doing the same thing with Either.
I am not trying to be polemic, just to see where the community stands: regarding Either/Maybe: do you have use cases for length (sum) too?
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort. In particular, the idea that one should make all such functions partial by throwing an error is repugnant. Kris On Thu, Mar 2, 2017 at 10:35 AM, Francesco Ariis <fa-ml@ariis.it> wrote:
On Thu, Mar 02, 2017 at 05:19:26PM +0000, Oliver Charles wrote:
Personally, I think it would be a shame to lose foldMap on EIther. I frequently foldMap over Maybe values (where mempty is suitable in case of "failure"), and I can certainly see myself doing the same thing with Either.
I am not trying to be polemic, just to see where the community stands: regarding Either/Maybe: do you have use cases for length (sum) too?
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Of course errors are swallowed. Look at the type signature. concat :: Foldable t => t [b] -> [b] -- t = Either a concat :: Either a [b] -> [b] The error type "a" does not appear anywhere in the function's output type. In the event of an error, the only thing it could possibly produce as output is an empty list. I don't think this means that Either's foldable instance is harmful and should be removed. It's a perfectly good instance that behaves in the "obvious" Maybe-like way. I do think this is an argument in favor of using a custom Prelude (which uses functions specialized to lists) when teaching new students. Any Traversable instance should absolutely be Foldable, with foldMap = foldMapDefault, or an optimized version that produces the same result. Putting `foldMap = error ...` for any Traversable is out of the question, imo. -- Dan Burton On Thu, Mar 2, 2017 at 10:12 AM, Kris Nuttycombe <kris.nuttycombe@gmail.com> wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
In particular, the idea that one should make all such functions partial by throwing an error is repugnant.
Kris
On Thu, Mar 2, 2017 at 10:35 AM, Francesco Ariis <fa-ml@ariis.it> wrote:
On Thu, Mar 02, 2017 at 05:19:26PM +0000, Oliver Charles wrote:
Personally, I think it would be a shame to lose foldMap on EIther. I frequently foldMap over Maybe values (where mempty is suitable in case of "failure"), and I can certainly see myself doing the same thing with Either.
I am not trying to be polemic, just to see where the community stands: regarding Either/Maybe: do you have use cases for length (sum) too?
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
foldMapDefault and fmapDefault *should* actually perform quite well, by the way, unless the specialized definitions come with rewrite rules. On Mar 2, 2017 1:50 PM, "Dan Burton" <danburton.email@gmail.com> wrote:
Of course errors are swallowed. Look at the type signature.
concat :: Foldable t => t [b] -> [b] -- t = Either a concat :: Either a [b] -> [b]
The error type "a" does not appear anywhere in the function's output type. In the event of an error, the only thing it could possibly produce as output is an empty list.
I don't think this means that Either's foldable instance is harmful and should be removed. It's a perfectly good instance that behaves in the "obvious" Maybe-like way. I do think this is an argument in favor of using a custom Prelude (which uses functions specialized to lists) when teaching new students.
Any Traversable instance should absolutely be Foldable, with foldMap = foldMapDefault, or an optimized version that produces the same result. Putting `foldMap = error ...` for any Traversable is out of the question, imo.
-- Dan Burton
On Thu, Mar 2, 2017 at 10:12 AM, Kris Nuttycombe < kris.nuttycombe@gmail.com> wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
In particular, the idea that one should make all such functions partial by throwing an error is repugnant.
Kris
On Thu, Mar 2, 2017 at 10:35 AM, Francesco Ariis <fa-ml@ariis.it> wrote:
On Thu, Mar 02, 2017 at 05:19:26PM +0000, Oliver Charles wrote:
Personally, I think it would be a shame to lose foldMap on EIther. I frequently foldMap over Maybe values (where mempty is suitable in case of "failure"), and I can certainly see myself doing the same thing with Either.
I am not trying to be polemic, just to see where the community stands: regarding Either/Maybe: do you have use cases for length (sum) too?
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
At least in terms of Either, I do not see a "universe of nicely polymorphic functions" here. I'd say applying a Foldable on a complex data structure build of all sorts of type constructors that involve Either (and tuples) is highly counterintuitive. For a start, the "sums-of-products" representation of data types is not stable under our Foldable instances. data D a = C1 a | C2 a a deriving (Foldable) gives you a completely different Foldable instance than its sums-of-product representation Either a (a, a) Andreas On 02.03.2017 19:12, Kris Nuttycombe wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
In particular, the idea that one should make all such functions partial by throwing an error is repugnant.
Kris
On Thu, Mar 2, 2017 at 10:35 AM, Francesco Ariis <fa-ml@ariis.it <mailto:fa-ml@ariis.it>> wrote:
On Thu, Mar 02, 2017 at 05:19:26PM +0000, Oliver Charles wrote: > Personally, I think it would be a shame to lose foldMap on EIther. I > frequently foldMap over Maybe values (where mempty is suitable in case of > "failure"), and I can certainly see myself doing the same thing with Either.
I am not trying to be polemic, just to see where the community stands: regarding Either/Maybe: do you have use cases for length (sum) too?
_______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries>
_______________________________________________ Libraries mailing list Libraries@haskell.org 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@gu.se http://www.cse.chalmers.se/~abela/
Hi, Francesco Ariis wrote:
I am not trying to be polemic, just to see where the community stands:
Well, personally, I would not miss neither Foldable nor Traversable instances of (Either b) or ((,) b) for even a fraction of a second. And I know many people who fully agrees. Henning summed it up very well, I think: https://mail.haskell.org/pipermail/libraries/2016-February/026678.html I am completely and utterly unconvinced by arguments along the lines that just because one of the standard types *can* be seen as a container type it must be seen that way, by everyone, no exceptions. That was never the intent of these types, as evidenced by their names and as evidenced by the inherent asymmetry of their instances. Pretending otherwise just creates confusion, of which there are plenty of instances, with more coming as per Andreas' initial mail. Further this generality buys very little if anything in practice as anyone who really needs the functionality can define their own instances or, better, introduce a custom type with a well-chosen name that clearly reflects the application in question. So, indeed, "all consistent but consistently useless", as Henning eloquently put it. To be concrete: after all, why would I write, for an x of type Either Int, say, foldl (+) 0 x and not simply either (const 0) id x ? I know what I find more readable, at least, and I'd be willing to bet on what is more maintainable as well as time passes and code is passed from one group of maintainers to another. Yes, I did see: Kris Nuttycombe wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly.
But I must say that strikes me as supremely odd: why on Earth should one *not* make direct use of instance methods if they make so much sense as is claimed? Well, I don't really expect any changes. This is just to say that there still are lots of people who find the push to instantiate Foldable and Traversable as widely as possible very unfortunate. Best, /Henrik This message and any attachment are intended solely for the addressee and may contain confidential information. If you have received this message in error, please send it back to me, and immediately delete it. Please do not use, copy or disclose the information contained in this message or in any attachment. Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. This message has been checked for viruses but the contents of an attachment may still contain software viruses which could damage your computer system, you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.
On Thu, Mar 2, 2017 at 1:12 PM, Kris Nuttycombe <kris.nuttycombe@gmail.com> wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
Not just polymorphic functions. Many higher-order type constructors have Foldable instances based on their parameters. For example, data Cofree f a = a :< f (Cofree f a) instance Foldable f => Foldable (Cofree f a) where foldMap f (a :< as) = f a <> foldMap (foldMap f) as Without the instance for Either b, we lose the instances for Cofree (Either b) and Cofree (Compose [] (Either b)), both of which seem reasonable and useful. In particular, the idea that one should make all such functions partial by
throwing an error is repugnant.
Yes, that seems like the worst possible solution. Better would be some way to give a warning when calling an overloaded function at a particular type. -- Dave Menendez <dave@zednenem.com> <http://www.eyrie.org/~zednenem/>
100% this. Cofree Maybe is a a nicely general encoding of a non-empty list that shows how closely related it is to a rose tree Cofree []. It'd lose its ability to be folded if Maybe ceased to be Foldable. When I'm showing how the cofree comonad works, I often take time to work up those examples along with Cofree ((->) e) as an (infinite) Moore machine. About 3-4 examples in, it usually clicks. instances on Either e, and Maybe, Identity, (,) e, etc. are all building blocks that are commonly used for larger things like this. As you enumerate all the simple functors we have lying around in Haskell, looking at what they do when you compute `Cofree f` or `Free f` tends to be quite informative. This teaching approach breaks down completely once you start cutting arbitrary holes in instance coverage and making everyone remember where those holes are. -Edward On Fri, Mar 3, 2017 at 5:04 PM, David Menendez <dave@zednenem.com> wrote:
On Thu, Mar 2, 2017 at 1:12 PM, Kris Nuttycombe <kris.nuttycombe@gmail.com
wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
Not just polymorphic functions. Many higher-order type constructors have Foldable instances based on their parameters. For example,
data Cofree f a = a :< f (Cofree f a)
instance Foldable f => Foldable (Cofree f a) where foldMap f (a :< as) = f a <> foldMap (foldMap f) as
Without the instance for Either b, we lose the instances for Cofree (Either b) and Cofree (Compose [] (Either b)), both of which seem reasonable and useful.
In particular, the idea that one should make all such functions partial by
throwing an error is repugnant.
Yes, that seems like the worst possible solution. Better would be some way to give a warning when calling an overloaded function at a particular type.
-- Dave Menendez <dave@zednenem.com> <http://www.eyrie.org/~zednenem/>
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
To Richard's point, though, the ability right now to have e.g. Cofree (Compose [] (Either b)) is in direct conflict with not allowing much simpler terms that no one would ever want to call, e.g.: sum ([1,2,3], 1) == 1 At the moment, we're picking points on the expressiveness-correctness spectrum. Would David's proposal of making Foldable a qualified import not allow us to have our cake and eat it too? Tom
El 3 mar 2017, a las 23:10, Edward Kmett <ekmett@gmail.com> escribió:
100% this. Cofree Maybe is a a nicely general encoding of a non-empty list that shows how closely related it is to a rose tree Cofree []. It'd lose its ability to be folded if Maybe ceased to be Foldable.
When I'm showing how the cofree comonad works, I often take time to work up those examples along with Cofree ((->) e) as an (infinite) Moore machine. About 3-4 examples in, it usually clicks.
instances on Either e, and Maybe, Identity, (,) e, etc. are all building blocks that are commonly used for larger things like this.
As you enumerate all the simple functors we have lying around in Haskell, looking at what they do when you compute `Cofree f` or `Free f` tends to be quite informative.
This teaching approach breaks down completely once you start cutting arbitrary holes in instance coverage and making everyone remember where those holes are.
-Edward
On Fri, Mar 3, 2017 at 5:04 PM, David Menendez <dave@zednenem.com> wrote:
On Thu, Mar 2, 2017 at 1:12 PM, Kris Nuttycombe <kris.nuttycombe@gmail.com> wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
Not just polymorphic functions. Many higher-order type constructors have Foldable instances based on their parameters. For example,
data Cofree f a = a :< f (Cofree f a)
instance Foldable f => Foldable (Cofree f a) where foldMap f (a :< as) = f a <> foldMap (foldMap f) as
Without the instance for Either b, we lose the instances for Cofree (Either b) and Cofree (Compose [] (Either b)), both of which seem reasonable and useful.
In particular, the idea that one should make all such functions partial by throwing an error is repugnant.
Yes, that seems like the worst possible solution. Better would be some way to give a warning when calling an overloaded function at a particular type.
-- Dave Menendez <dave@zednenem.com> <http://www.eyrie.org/~zednenem/>
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
It would thrash the entire community back more than half-way to where things stood before the Foldable/Traversable proposal and force us back into a world of qualified imports. Everyone who has adapted their code to the status quo over the last 2-3 years and have enjoyed the benefit of a base that doesn't have any internal conflicts would have to go through all the work of reverting their code, or add yet more CPP to hack around the mess. That strikes me, on balance, as a bad option. -Edward On Sat, Mar 4, 2017 at 9:16 PM, <amindfv@gmail.com> wrote:
To Richard's point, though, the ability right now to have e.g. Cofree (Compose [] (Either b)) is in direct conflict with not allowing much simpler terms that no one would ever want to call, e.g.:
sum ([1,2,3], 1) == 1
At the moment, we're picking points on the expressiveness-correctness spectrum.
Would David's proposal of making Foldable a qualified import not allow us to have our cake and eat it too?
Tom
El 3 mar 2017, a las 23:10, Edward Kmett <ekmett@gmail.com> escribió:
100% this. Cofree Maybe is a a nicely general encoding of a non-empty list that shows how closely related it is to a rose tree Cofree []. It'd lose its ability to be folded if Maybe ceased to be Foldable.
When I'm showing how the cofree comonad works, I often take time to work up those examples along with Cofree ((->) e) as an (infinite) Moore machine. About 3-4 examples in, it usually clicks.
instances on Either e, and Maybe, Identity, (,) e, etc. are all building blocks that are commonly used for larger things like this.
As you enumerate all the simple functors we have lying around in Haskell, looking at what they do when you compute `Cofree f` or `Free f` tends to be quite informative.
This teaching approach breaks down completely once you start cutting arbitrary holes in instance coverage and making everyone remember where those holes are.
-Edward
On Fri, Mar 3, 2017 at 5:04 PM, David Menendez <dave@zednenem.com> wrote:
On Thu, Mar 2, 2017 at 1:12 PM, Kris Nuttycombe < kris.nuttycombe@gmail.com> wrote:
As with all of these discussions, the point of having Either be Foldable is not that you're going to call foldMap on an Either value directly. Instead, it is that you be able to pass whatever sort of foldable thing you choose (which Either certainly is) to a function that only requires foldability of its input. By removing or damaging the Foldable instance for Either, you don't simply prevent people from encountering problems that will be resolved the first time they test their software - you make a whole universe of nicely polymorphic functions unavailable for them to use without additional effort.
Not just polymorphic functions. Many higher-order type constructors have Foldable instances based on their parameters. For example,
data Cofree f a = a :< f (Cofree f a)
instance Foldable f => Foldable (Cofree f a) where foldMap f (a :< as) = f a <> foldMap (foldMap f) as
Without the instance for Either b, we lose the instances for Cofree (Either b) and Cofree (Compose [] (Either b)), both of which seem reasonable and useful.
In particular, the idea that one should make all such functions partial
by throwing an error is repugnant.
Yes, that seems like the worst possible solution. Better would be some way to give a warning when calling an overloaded function at a particular type.
-- Dave Menendez <dave@zednenem.com> <http://www.eyrie.org/~zednenem/>
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Anecdotally, today I wrote `foldMap toList`, to use as `Maybe (NonEmpty a) -> [a]`. Also I rely heavily in lens-based code on the `folded :: Fold (Maybe a) a`. So :-1: for me. OTOH :+1: for using non-default preludes for teaching. - Oleg On 02.03.2017 19:35, Francesco Ariis wrote:
On Thu, Mar 02, 2017 at 05:19:26PM +0000, Oliver Charles wrote:
Personally, I think it would be a shame to lose foldMap on EIther. I frequently foldMap over Maybe values (where mempty is suitable in case of "failure"), and I can certainly see myself doing the same thing with Either. I am not trying to be polemic, just to see where the community stands: regarding Either/Maybe: do you have use cases for length (sum) too?
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
We had a very similar discussion this time last year ( https://mail.haskell.org/pipermail/libraries/2016-February/026678.html), with many people on both sides of the issue. There wasn't enough agreement reached to change the status quo. I'll just repeat two things from that discussion: - This is *not* just an issue of "beginners may be confused": Andrew Farmer describes encountering what I think is the most disconcerting part of having these instances: you can no longer have confidence in the process of change-the-type-then-just-fix-the-type-errors: https://mail.haskell.org/pipermail/libraries/2016-February/026782.html - The tl;dr of my argument last time: "Part of the power of a type system is which program it rejects, and I'm arguing we're cluttering the space of valid programs." The last time this was discussed, we planned to implement a flag to forbid certain instances. Has anyone taken that up? Tom On Thu, Mar 2, 2017 at 5:35 PM, Oleg Grenrus <oleg.grenrus@iki.fi> wrote:
Anecdotally, today I wrote `foldMap toList`, to use as `Maybe (NonEmpty a) -> [a]`. Also I rely heavily in lens-based code on the `folded :: Fold (Maybe a) a`.
So :-1: for me.
OTOH :+1: for using non-default preludes for teaching.
- Oleg
On 02.03.2017 19:35, Francesco Ariis wrote:
On Thu, Mar 02, 2017 at 05:19:26PM +0000, Oliver Charles wrote:
Personally, I think it would be a shame to lose foldMap on EIther. I frequently foldMap over Maybe values (where mempty is suitable in case of "failure"), and I can certainly see myself doing the same thing with Either. I am not trying to be polemic, just to see where the community stands: regarding Either/Maybe: do you have use cases for length (sum) too?
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
On Thu, Mar 2, 2017 at 11:59 AM, Andreas Abel <andreas.abel@ifi.lmu.de> wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
This would change the semantic of every forM_ myeither $ \i -> .... in existing code to silent errors. Hell no. -Edward
On 02.03.2017 17:48, David Feuer wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html>
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se <mailto:andreas.abel@gu.se> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~a bela/> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se http://www.cse.chalmers.se/~abela/ _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
We could have a module Data.List.ReallyJustListsAndNotSomeThingMoreGeneric which implements concat and friends just for lists and could be imported if one wants to have the list operations. Currently, import qualified Data.List as List does not give on the list operations as e.g. List.concat but the generic ones. See also http://ghc.haskell.org/trac/ghc/ticket/13345 On 02.03.2017 20:02, Edward Kmett wrote:
On Thu, Mar 2, 2017 at 11:59 AM, Andreas Abel <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>> wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
This would change the semantic of every
forM_ myeither $ \i -> ....
in existing code to silent errors.
Hell no.
-Edward
On 02.03.2017 17:48, David Feuer wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de> <mailto:andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>>> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/026678.html>
<https://mail.haskell.org/pipermail/libraries/2016-February/026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/026678.html>>
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se <mailto:andreas.abel@gu.se> <mailto:andreas.abel@gu.se <mailto:andreas.abel@gu.se>> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> <http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/>> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> <mailto:Libraries@haskell.org <mailto:Libraries@haskell.org>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries> <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se <mailto:andreas.abel@gu.se> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se http://www.cse.chalmers.se/~abela/
Yes. That is an excellent plan. I'd love to call it Data.List, but others will disagree. On Mar 2, 2017 2:17 PM, "Andreas Abel" <andreas.abel@ifi.lmu.de> wrote:
We could have a module
Data.List.ReallyJustListsAndNotSomeThingMoreGeneric
which implements concat and friends just for lists and could be imported if one wants to have the list operations. Currently,
import qualified Data.List as List
does not give on the list operations as e.g.
List.concat
but the generic ones.
See also http://ghc.haskell.org/trac/ghc/ticket/13345
On 02.03.2017 20:02, Edward Kmett wrote:
On Thu, Mar 2, 2017 at 11:59 AM, Andreas Abel <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>> wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
This would change the semantic of every
forM_ myeither $ \i -> ....
in existing code to silent errors.
Hell no.
-Edward
On 02.03.2017 17:48, David Feuer wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de> <mailto:andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>>> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html>
<https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html>>
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se <mailto:andreas.abel@gu.se> <mailto:andreas.abel@gu.se <mailto:andreas.abel@gu.se>> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> <http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/>> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> <mailto:Libraries@haskell.org <mailto:Libraries@haskell.org>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries> <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se <mailto:andreas.abel@gu.se> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~a bela/> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se http://www.cse.chalmers.se/~abela/
Sadly, doing so in Data.List would lead to massive breakage as Data.List is specified by the report and is very, very widely imported unqualified just to get at things like sort. -Edward On Thu, Mar 2, 2017 at 2:28 PM, David Feuer <david.feuer@gmail.com> wrote:
Yes. That is an excellent plan. I'd love to call it Data.List, but others will disagree.
On Mar 2, 2017 2:17 PM, "Andreas Abel" <andreas.abel@ifi.lmu.de> wrote:
We could have a module
Data.List.ReallyJustListsAndNotSomeThingMoreGeneric
which implements concat and friends just for lists and could be imported if one wants to have the list operations. Currently,
import qualified Data.List as List
does not give on the list operations as e.g.
List.concat
but the generic ones.
See also http://ghc.haskell.org/trac/ghc/ticket/13345
On 02.03.2017 20:02, Edward Kmett wrote:
On Thu, Mar 2, 2017 at 11:59 AM, Andreas Abel <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>> wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
This would change the semantic of every
forM_ myeither $ \i -> ....
in existing code to silent errors.
Hell no.
-Edward
On 02.03.2017 17:48, David Feuer wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de> <mailto:andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>>> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/0 26678.html <https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html>
<https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html>>
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se <mailto:andreas.abel@gu.se> <mailto:andreas.abel@gu.se <mailto:andreas.abel@gu.se>> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> <http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/>> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> <mailto:Libraries@haskell.org <mailto:Libraries@haskell.org>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries> <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se <mailto:andreas.abel@gu.se> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~a bela/> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se http://www.cse.chalmers.se/~abela/
On 3 March 2017 at 06:28, David Feuer <david.feuer@gmail.com> wrote:
Yes. That is an excellent plan. I'd love to call it Data.List, but others will disagree.
Same here. I wasn't that happy with the FTP proposal when it first came up due to potential confusions (primarily due to naming conventions like "length"), but now that it's done we shouldn't go back. So -1 on the proposal.
On Mar 2, 2017 2:17 PM, "Andreas Abel" <andreas.abel@ifi.lmu.de> wrote:
We could have a module
Data.List.ReallyJustListsAndNotSomeThingMoreGeneric
which implements concat and friends just for lists and could be imported if one wants to have the list operations. Currently,
import qualified Data.List as List
does not give on the list operations as e.g.
List.concat
but the generic ones.
See also http://ghc.haskell.org/trac/ghc/ticket/13345
On 02.03.2017 20:02, Edward Kmett wrote:
On Thu, Mar 2, 2017 at 11:59 AM, Andreas Abel <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>> wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
This would change the semantic of every
forM_ myeither $ \i -> ....
in existing code to silent errors.
Hell no.
-Edward
On 02.03.2017 17:48, David Feuer wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de> <mailto:andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>>> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
<https://mail.haskell.org/pipermail/libraries/2016-February/026678.html>
<https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
<https://mail.haskell.org/pipermail/libraries/2016-February/026678.html>>
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se <mailto:andreas.abel@gu.se> <mailto:andreas.abel@gu.se <mailto:andreas.abel@gu.se>> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> <http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/>> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> <mailto:Libraries@haskell.org <mailto:Libraries@haskell.org>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries> <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se <mailto:andreas.abel@gu.se> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se http://www.cse.chalmers.se/~abela/
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
-- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com http://IvanMiljenovic.wordpress.com
On Fri, 3 Mar 2017, Ivan Lazar Miljenovic wrote:
On 3 March 2017 at 06:28, David Feuer <david.feuer@gmail.com> wrote:
Yes. That is an excellent plan. I'd love to call it Data.List, but others will disagree.
Same here.
I wasn't that happy with the FTP proposal when it first came up due to potential confusions (primarily due to naming conventions like "length"), but now that it's done we shouldn't go back.
We should have at least compiler warnings for those who care.
for what? lets just have a learners / grumpy people prelude On Fri, Mar 17, 2017 at 8:31 AM, Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Fri, 3 Mar 2017, Ivan Lazar Miljenovic wrote:
On 3 March 2017 at 06:28, David Feuer <david.feuer@gmail.com> wrote:
Yes. That is an excellent plan. I'd love to call it Data.List, but others will disagree.
Same here.
I wasn't that happy with the FTP proposal when it first came up due to potential confusions (primarily due to naming conventions like "length"), but now that it's done we shouldn't go back.
We should have at least compiler warnings for those who care.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache. You could make that an hlint rule on the other hand.
On Sat, 18 Mar 2017, Lana Black wrote:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used.
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions.
Whether the warning is enabled by Wall is a different question. Though I think it should. https://ghc.haskell.org/trac/ghc/ticket/11796
I'm +1 on offering the warning and very very -1 on including it in -Wall. On Mar 18, 2017 6:19 PM, "Henning Thielemann" <lemming@henning-thielemann.de> wrote:
On Sat, 18 Mar 2017, Lana Black wrote:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used.
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions.
Whether the warning is enabled by Wall is a different question. Though I think it should.
https://ghc.haskell.org/trac/ghc/ticket/11796 _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
I will fork the compiler before I endure that degree of failure. On 19/03/17 08:21, David Feuer wrote:
I'm +1 on offering the warning and very very -1 on including it in -Wall.
On Mar 18, 2017 6:19 PM, "Henning Thielemann" <lemming@henning-thielemann.de <mailto:lemming@henning-thielemann.de>> wrote:
On Sat, 18 Mar 2017, Lana Black wrote:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used.
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions.
Whether the warning is enabled by Wall is a different question. Though I think it should.
https://ghc.haskell.org/trac/ghc/ticket/11796 <https://ghc.haskell.org/trac/ghc/ticket/11796> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries>
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
On Sun, 19 Mar 2017, Tony Morris wrote:
I will fork the compiler before I endure that degree of failure.
That's a reasonable approach. If you would have forked the compiler in order to implement the FTP and all the Foldable tuple instances only in the fork then we would not need the warnings, at all.
I already implemented all of that over 10 years ago. All I need is NoImplicitPrelude and I can fly under the radar, with the outcome of not-really-debates having nil practical effect. I'm just pointing to the approaching threshold in nose-down trim. I've code to write now. Expedited bug out. On 19/03/17 20:09, Henning Thielemann wrote:
On Sun, 19 Mar 2017, Tony Morris wrote:
I will fork the compiler before I endure that degree of failure.
That's a reasonable approach. If you would have forked the compiler in order to implement the FTP and all the Foldable tuple instances only in the fork then we would not need the warnings, at all.
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint. I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion). Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
I'm on the fence about the instance existing. I'm +1 for a warning, and thus would be +1 on keeping the instance. +1 on making the warning opt-in and +1 keeping it out of -Wall. On Sun, 19 Mar 2017 at 00:51 <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Is there a clear way to implement this instance warning? I.e. given: f x = 2 * length x Can we guarantee at compile time that "f" will never be passed a 2-tuple? Tom
El 18 mar 2017, a las 20:04, Adam Bergmark <adam@bergmark.nl> escribió:
I'm on the fence about the instance existing. I'm +1 for a warning, and thus would be +1 on keeping the instance. +1 on making the warning opt-in and +1 keeping it out of -Wall.
On Sun, 19 Mar 2017 at 00:51 <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
This would have to be determined and triggered at the use site of `f' since `f :: Foldable t => t a -> Int'. As long as you stay generic the user of your function will decide whether he wants the warning. If you choose to specialize your function to a 2-tuple you would get the warning. Adam On Sun, 19 Mar 2017 at 17:14 <amindfv@gmail.com> wrote:
Is there a clear way to implement this instance warning? I.e. given:
f x = 2 * length x
Can we guarantee at compile time that "f" will never be passed a 2-tuple?
Tom
El 18 mar 2017, a las 20:04, Adam Bergmark <adam@bergmark.nl> escribió:
I'm on the fence about the instance existing. I'm +1 for a warning, and thus would be +1 on keeping the instance. +1 on making the warning opt-in and +1 keeping it out of -Wall.
On Sun, 19 Mar 2017 at 00:51 <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
On Sun, 19 Mar 2017, amindfv@gmail.com wrote:
Is there a clear way to implement this instance warning? I.e. given:
f x = 2 * length x
Can we guarantee at compile time that "f" will never be passed a 2-tuple?
I gave an idea in the ticket: https://ghc.haskell.org/trac/ghc/ticket/11796 Defining f this way would be ok if x is polymorphic. The warning would only arise if f is applied to a pair.
That you can't should be a hint that length for ((,) a) is very definitely 1. Simply, use a different function, not length, which is well-defined for ((,) a) and other instances. On Mon, Mar 20, 2017 at 3:15 AM, <amindfv@gmail.com> wrote:
Is there a clear way to implement this instance warning? I.e. given:
f x = 2 * length x
Can we guarantee at compile time that "f" will never be passed a 2-tuple?
Tom
El 18 mar 2017, a las 20:04, Adam Bergmark <adam@bergmark.nl> escribió:
I'm on the fence about the instance existing. I'm +1 for a warning, and thus would be +1 on keeping the instance. +1 on making the warning opt-in and +1 keeping it out of -Wall.
On Sun, 19 Mar 2017 at 00:51 <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
El 19 mar 2017, a las 17:19, Tony Morris <tmorris@tmorris.net> escribió:
That you can't should be a hint that length for ((,) a) is very definitely 1.
To be frank, this seems like a non-sequitur. Many of us find e.g.: length (_, _) = 1 maximum (_, b) = b to be dangerous instances. We don't want to accidentally call them. We'd like a way to opt out or warn on use. The inability to opt out or be warned does not seem to me to be an argument that the above instances are good instances. Feel free to clarify if I haven't understood your point. Thanks! Tom
Simply, use a different function, not length, which is well-defined for ((,) a) and other instances.
On Mon, Mar 20, 2017 at 3:15 AM, <amindfv@gmail.com> wrote: Is there a clear way to implement this instance warning? I.e. given:
f x = 2 * length x
Can we guarantee at compile time that "f" will never be passed a 2-tuple?
Tom
El 18 mar 2017, a las 20:04, Adam Bergmark <adam@bergmark.nl> escribió:
I'm on the fence about the instance existing. I'm +1 for a warning, and thus would be +1 on keeping the instance. +1 on making the warning opt-in and +1 keeping it out of -Wall.
On Sun, 19 Mar 2017 at 00:51 <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
> On Sat, 18 Mar 2017, Carter Schonwald wrote: > > for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
The criteria for determining this apparent danger, in all cases I have seen, is arbitrary nonsense. Try defining it in a coherent way. "But the inconsistency with my intuition for the function named l-e-n-g-t-h that I learned in C programming school in the 1980s" is the best criteria that I have seen, and which commands outright dismissal. I am sceptical of anything better, and therefore, worth considering. Other contenders: * feels bad in my bones * don't like it * there's lots of us! All these arguments have been, by moral imperative, and in practice, dismissed. The length of ((,) a) is very definitely 1. That this is not bleedingly obvious, busted intuitions aside, is becoming more laborious as this not-really-debate drags on. We have a kind system, we have a type system, we have parametricity. Use them. If you choose not to, fine, but don't try to take superior tools away from me for no benefit. I will stop you. ---- An anecdote on danger. A twin piston engine aircraft recently crashed into a shopping centre on take-off from an airport in southern Australia. All onboard were killed. Nobody on the ground was injured. The cause is yet unknown and is under investigation. It is an unusual circumstance. A friend of mine declared to me that the airport should be closed. When I asked why, I was told, "I used to work in the same type of shopping centre, at a different airport, and I felt like I was in danger when aeroplanes flew overhead." It is extremely fortunate that we don't have such ridiculous assessments of danger dictating the policies of aviation safety. Indeed, flying aeroplanes is one very effective way to get away from that nonsense. Imagine if that "sense of danger" were to dictate aviation safety regulations. What a dangerous world we would be living in! ---- Ask yourself where the danger is and be reasonable about it. Hope that helps. On 20/03/17 10:30, amindfv@gmail.com wrote:
El 19 mar 2017, a las 17:19, Tony Morris <tmorris@tmorris.net <mailto:tmorris@tmorris.net>> escribió:
That you can't should be a hint that length for ((,) a) is very definitely 1.
To be frank, this seems like a non-sequitur. Many of us find e.g.:
length (_, _) = 1 maximum (_, b) = b
to be dangerous instances. We don't want to accidentally call them. We'd like a way to opt out or warn on use.
The inability to opt out or be warned does not seem to me to be an argument that the above instances are good instances.
Feel free to clarify if I haven't understood your point.
Thanks! Tom
Simply, use a different function, not length, which is well-defined for ((,) a) and other instances.
On Mon, Mar 20, 2017 at 3:15 AM, <amindfv@gmail.com <mailto:amindfv@gmail.com>> wrote:
Is there a clear way to implement this instance warning? I.e. given:
f x = 2 * length x
Can we guarantee at compile time that "f" will never be passed a 2-tuple?
Tom
El 18 mar 2017, a las 20:04, Adam Bergmark <adam@bergmark.nl <mailto:adam@bergmark.nl>> escribió:
I'm on the fence about the instance existing. I'm +1 for a warning, and thus would be +1 on keeping the instance. +1 on making the warning opt-in and +1 keeping it out of -Wall.
On Sun, 19 Mar 2017 at 00:51 <amindfv@gmail.com <mailto:amindfv@gmail.com>> wrote:
> El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc <mailto:lanablack@amok.cc>> escribió: > >> On 18/03/17 19:49, Henning Thielemann wrote: >> >>> On Sat, 18 Mar 2017, Carter Schonwald wrote: >>> >>> for what? >> >> A warning if someone e.g. calls 'length (a,b)', or more generally, if >> certain instances are used. >> _______________________________________________ >> Libraries mailing list >> Libraries@haskell.org <mailto:Libraries@haskell.org> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries> > > Please no. Many of us like our code Wall-clean while still being able to > write polymorphic functions. Adding more warnings that are often > triggered by correct code (redundant constraints, anyone?) only leads to > more headache. > > You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
> _______________________________________________ > Libraries mailing list > Libraries@haskell.org <mailto:Libraries@haskell.org> > http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries>
_______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries>
Sadly, hlint remains fairly (er.. completely?) ignorant of the types of an expression. It has no idea what is in scope, and just provides syntax-directed guidance, so hlint isn't the answer here. That said, there does seem to be a plausible solution available. I have zero objection to adding {-# POISON #-} pragma that users could include in their own code that just makes it so that whatever instance is named inside of it becomes unusable. You could view it as setting up an ambiguous instance declaration that is currently impossible to write, so any attempt to use the instance would complain about ambiguous instances (or preferably about the instance being poisoned and name the source of the poison). This would make the status quo the norm, but then you could modify your custom Prelude or what have you to {-# POISON instance Foldable ((,) e) #-} and then any code that transitively depended on your Prelude would complain if it attempted to use that instance. Such a poison pragma should be sound with respect to GHC's internals. It is effectively making an extra instance just to cause conflicts later on in the instance selection process. This is the same as if we had Foldable the class being defined in one module, the real instance in another, someone's poison instance in a third, then a fourth module that imports the whole diamond. Any attempt to use the instance that is defined in two contradictory ways in that 4th module today will complain. Folks who care about these instances would then have the choice about whether to avoid any package that poisoned any instances they cared about, and folks who fee strongly about this issue would be able to live in a world where these instances didn't affect any code they wrote and if they didn't want to turn off users that care about being poisoned, could turn on the poisoning through cabal flags so that they don't infect their API but get an opt-in internal consistency check for local compilation. -Edward Kmett P.S. The term poison above derives from the C convention of poisoning names you don't want to see in your code due to safety considerations. e.g. In GCC you can do so with #pragma GCC poison printf sprintf fprintf On Sat, Mar 18, 2017 at 8:51 PM, <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Edward: this is clever! I can't at the moment see any reason this wouldn't work for all parties: those who want the instances can have them, those who don't can "turn them off," and beginners can start with a prelude that turns them off also. We will need to be clear about which packages (transitively) poison instances. Tom
El 19 mar 2017, a las 19:21, Edward Kmett <ekmett@gmail.com> escribió:
Sadly, hlint remains fairly (er.. completely?) ignorant of the types of an expression. It has no idea what is in scope, and just provides syntax-directed guidance, so hlint isn't the answer here.
That said, there does seem to be a plausible solution available.
I have zero objection to adding {-# POISON #-} pragma that users could include in their own code that just makes it so that whatever instance is named inside of it becomes unusable. You could view it as setting up an ambiguous instance declaration that is currently impossible to write, so any attempt to use the instance would complain about ambiguous instances (or preferably about the instance being poisoned and name the source of the poison).
This would make the status quo the norm, but then you could modify your custom Prelude or what have you to {-# POISON instance Foldable ((,) e) #-} and then any code that transitively depended on your Prelude would complain if it attempted to use that instance.
Such a poison pragma should be sound with respect to GHC's internals. It is effectively making an extra instance just to cause conflicts later on in the instance selection process. This is the same as if we had Foldable the class being defined in one module, the real instance in another, someone's poison instance in a third, then a fourth module that imports the whole diamond. Any attempt to use the instance that is defined in two contradictory ways in that 4th module today will complain.
Folks who care about these instances would then have the choice about whether to avoid any package that poisoned any instances they cared about, and folks who fee strongly about this issue would be able to live in a world where these instances didn't affect any code they wrote and if they didn't want to turn off users that care about being poisoned, could turn on the poisoning through cabal flags so that they don't infect their API but get an opt-in internal consistency check for local compilation.
-Edward Kmett
P.S. The term poison above derives from the C convention of poisoning names you don't want to see in your code due to safety considerations. e.g. In GCC you can do so with
#pragma GCC poison printf sprintf fprintf
On Sat, Mar 18, 2017 at 8:51 PM, <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Ed, If i understand you correctly then this poisoning doesn't scale. If I want to use it in my library I'm also forcing all my users to avoid these functions and it would split hackage in half. Effectively I'd only be able to use it for private code and applications. Or am I misunderstanding? You can already do this in poisoning in a solid way by defining e.g. `class Unsatisfiable; instance Unsatisfiable => Show (a -> b) where show = undefined` and not exporting Unsatisfiable. Cheers, Adam On Mon, 20 Mar 2017 at 01:56 <amindfv@gmail.com> wrote:
Edward: this is clever! I can't at the moment see any reason this wouldn't work for all parties: those who want the instances can have them, those who don't can "turn them off," and beginners can start with a prelude that turns them off also.
We will need to be clear about which packages (transitively) poison instances.
Tom
El 19 mar 2017, a las 19:21, Edward Kmett <ekmett@gmail.com> escribió:
Sadly, hlint remains fairly (er.. completely?) ignorant of the types of an expression. It has no idea what is in scope, and just provides syntax-directed guidance, so hlint isn't the answer here.
That said, there does seem to be a plausible solution available.
I have zero objection to adding {-# POISON #-} pragma that users could include in their own code that just makes it so that whatever instance is named inside of it becomes unusable. You could view it as setting up an ambiguous instance declaration that is currently impossible to write, so any attempt to use the instance would complain about ambiguous instances (or preferably about the instance being poisoned and name the source of the poison).
This would make the status quo the norm, but then you could modify your custom Prelude or what have you to {-# POISON instance Foldable ((,) e) #-} and then any code that transitively depended on your Prelude would complain if it attempted to use that instance.
Such a poison pragma should be sound with respect to GHC's internals. It is effectively making an extra instance just to cause conflicts later on in the instance selection process. This is the same as if we had Foldable the class being defined in one module, the real instance in another, someone's poison instance in a third, then a fourth module that imports the whole diamond. Any attempt to use the instance that is defined in two contradictory ways in that 4th module today will complain.
Folks who care about these instances would then have the choice about whether to avoid any package that poisoned any instances they cared about, and folks who fee strongly about this issue would be able to live in a world where these instances didn't affect any code they wrote and if they didn't want to turn off users that care about being poisoned, could turn on the poisoning through cabal flags so that they don't infect their API but get an opt-in internal consistency check for local compilation.
-Edward Kmett
P.S. The term poison above derives from the C convention of poisoning names you don't want to see in your code due to safety considerations. e.g. In GCC you can do so with
#pragma GCC poison printf sprintf fprintf
On Sat, Mar 18, 2017 at 8:51 PM, <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
El 19 mar 2017, a las 20:33, Adam Bergmark <adam@bergmark.nl> escribió:
Ed, If i understand you correctly then this poisoning doesn't scale. If I want to use it in my library I'm also forcing all my users to avoid these functions and it would split hackage in half. Effectively I'd only be able to use it for private code and applications. Or am I misunderstanding?
I think the idea is you can check that your library compiles cleanly with "-wpoison 'Foldable ((,) a)' " etc, but then you don't actually "put the poison in" your library (unless you feel that strongly about it) Tom
You can already do this in poisoning in a solid way by defining e.g. `class Unsatisfiable; instance Unsatisfiable => Show (a -> b) where show = undefined` and not exporting Unsatisfiable.
Cheers, Adam
On Mon, 20 Mar 2017 at 01:56 <amindfv@gmail.com> wrote: Edward: this is clever! I can't at the moment see any reason this wouldn't work for all parties: those who want the instances can have them, those who don't can "turn them off," and beginners can start with a prelude that turns them off also.
We will need to be clear about which packages (transitively) poison instances.
Tom
El 19 mar 2017, a las 19:21, Edward Kmett <ekmett@gmail.com> escribió:
Sadly, hlint remains fairly (er.. completely?) ignorant of the types of an expression. It has no idea what is in scope, and just provides syntax-directed guidance, so hlint isn't the answer here.
That said, there does seem to be a plausible solution available.
I have zero objection to adding {-# POISON #-} pragma that users could include in their own code that just makes it so that whatever instance is named inside of it becomes unusable. You could view it as setting up an ambiguous instance declaration that is currently impossible to write, so any attempt to use the instance would complain about ambiguous instances (or preferably about the instance being poisoned and name the source of the poison).
This would make the status quo the norm, but then you could modify your custom Prelude or what have you to {-# POISON instance Foldable ((,) e) #-} and then any code that transitively depended on your Prelude would complain if it attempted to use that instance.
Such a poison pragma should be sound with respect to GHC's internals. It is effectively making an extra instance just to cause conflicts later on in the instance selection process. This is the same as if we had Foldable the class being defined in one module, the real instance in another, someone's poison instance in a third, then a fourth module that imports the whole diamond. Any attempt to use the instance that is defined in two contradictory ways in that 4th module today will complain.
Folks who care about these instances would then have the choice about whether to avoid any package that poisoned any instances they cared about, and folks who fee strongly about this issue would be able to live in a world where these instances didn't affect any code they wrote and if they didn't want to turn off users that care about being poisoned, could turn on the poisoning through cabal flags so that they don't infect their API but get an opt-in internal consistency check for local compilation.
-Edward Kmett
P.S. The term poison above derives from the C convention of poisoning names you don't want to see in your code due to safety considerations. e.g. In GCC you can do so with
#pragma GCC poison printf sprintf fprintf
On Sat, Mar 18, 2017 at 8:51 PM, <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
On Sun, Mar 19, 2017 at 9:33 PM, Adam Bergmark <adam@bergmark.nl> wrote:
Ed, If i understand you correctly then this poisoning doesn't scale. If I want to use it in my library I'm also forcing all my users to avoid these functions and it would split hackage in half. Effectively I'd only be able to use it for private code and applications. Or am I misunderstanding?
This is why I mentioned at the end that if you're doing this for a library you probably only want to enable poisoning with a cabal build flag. That way you can use it to verify that you build clean even with the poison enabled without crippling your users. Think of it like -Werror. You don't ship cabal packages with it enabled but you often use it locally. For classroom teaching scenarios using a custom prelude that poisons things fits the bill. If you are concerned about certain instances leaking into your private code, you can also poison willy-nilly, and nobody needs care. If you poison behind a flag it doesn't leak out into the ecosystem, and if you choose not to poison behind a flag, then people can choose to accept or reject your poisoned instances on their own merits. e.g. async had an instance of Monad for Concurrently that was incompatible with its Applicative until recently. Fortunately, Simon Marlow was willing to listen to reason. However, had he not been, it is a situation where I could bring myself to resort to poison. Er... that sounds rather more gruesome than intended. Sorry, Simon. :) You can already do this in poisoning in a solid way by defining e.g. `class
Unsatisfiable; instance Unsatisfiable => Show (a -> b) where show = undefined` and not exporting Unsatisfiable.
Yes, if you want to ensure that an instance is never defined, but that doesn't work for things where there is already an instance in scope. You can't retroactively poison Foldable ((,) e) with this technique, as the class and instance are defined together in the same module (or the data type and instance are), as they have to be to avoid orphans, and so you never get a chance to interject a conflicting poisonous instance without GHC telling you that your instance collides with the existing instance as an error. -Edward Cheers,
Adam
On Mon, 20 Mar 2017 at 01:56 <amindfv@gmail.com> wrote:
Edward: this is clever! I can't at the moment see any reason this wouldn't work for all parties: those who want the instances can have them, those who don't can "turn them off," and beginners can start with a prelude that turns them off also.
We will need to be clear about which packages (transitively) poison instances.
Tom
El 19 mar 2017, a las 19:21, Edward Kmett <ekmett@gmail.com> escribió:
Sadly, hlint remains fairly (er.. completely?) ignorant of the types of an expression. It has no idea what is in scope, and just provides syntax-directed guidance, so hlint isn't the answer here.
That said, there does seem to be a plausible solution available.
I have zero objection to adding {-# POISON #-} pragma that users could include in their own code that just makes it so that whatever instance is named inside of it becomes unusable. You could view it as setting up an ambiguous instance declaration that is currently impossible to write, so any attempt to use the instance would complain about ambiguous instances (or preferably about the instance being poisoned and name the source of the poison).
This would make the status quo the norm, but then you could modify your custom Prelude or what have you to {-# POISON instance Foldable ((,) e) #-} and then any code that transitively depended on your Prelude would complain if it attempted to use that instance.
Such a poison pragma should be sound with respect to GHC's internals. It is effectively making an extra instance just to cause conflicts later on in the instance selection process. This is the same as if we had Foldable the class being defined in one module, the real instance in another, someone's poison instance in a third, then a fourth module that imports the whole diamond. Any attempt to use the instance that is defined in two contradictory ways in that 4th module today will complain.
Folks who care about these instances would then have the choice about whether to avoid any package that poisoned any instances they cared about, and folks who fee strongly about this issue would be able to live in a world where these instances didn't affect any code they wrote and if they didn't want to turn off users that care about being poisoned, could turn on the poisoning through cabal flags so that they don't infect their API but get an opt-in internal consistency check for local compilation.
-Edward Kmett
P.S. The term poison above derives from the C convention of poisoning names you don't want to see in your code due to safety considerations. e.g. In GCC you can do so with
#pragma GCC poison printf sprintf fprintf
On Sat, Mar 18, 2017 at 8:51 PM, <amindfv@gmail.com> wrote:
El 18 mar 2017, a las 16:01, Lana Black <lanablack@amok.cc> escribió:
On 18/03/17 19:49, Henning Thielemann wrote:
On Sat, 18 Mar 2017, Carter Schonwald wrote:
for what?
A warning if someone e.g. calls 'length (a,b)', or more generally, if certain instances are used. _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Please no. Many of us like our code Wall-clean while still being able to write polymorphic functions. Adding more warnings that are often triggered by correct code (redundant constraints, anyone?) only leads to more headache.
You could make that an hlint rule on the other hand.
Can it be a hlint rule? It seems quite difficult to predict that "length" will not ever be passed e.g. a 2-tuple in the general case, within hlint.
I would also favor a warning, and happily have -Wall not include it (though I'd prefer inclusion).
Tom
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
The issue is that if a "grumpy person" imports any library which uses the Prelude (I have a feeling they might), then under the open world assumption they will get the instances that to them are broken. If we can get a warning then those of us who find the instances dangerous might be more willing to live and let live. Tom
El 18 mar 2017, a las 14:21, Carter Schonwald <carter.schonwald@gmail.com> escribió:
for what?
lets just have a learners / grumpy people prelude
On Fri, Mar 17, 2017 at 8:31 AM, Henning Thielemann <lemming@henning-thielemann.de> wrote:
On Fri, 3 Mar 2017, Ivan Lazar Miljenovic wrote:
On 3 March 2017 at 06:28, David Feuer <david.feuer@gmail.com> wrote: Yes. That is an excellent plan. I'd love to call it Data.List, but others will disagree.
Same here.
I wasn't that happy with the FTP proposal when it first came up due to potential confusions (primarily due to naming conventions like "length"), but now that it's done we shouldn't go back.
We should have at least compiler warnings for those who care.
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
The nice thing about such a module is anybody can package it up. It needs nothing special from base. During the discussion about Foldable, the option to add a Data.List.Explicit or something that contained just the monomorphic variants was brought up as something we could add, but nobody really got enthusiastic over the idea. The state of Data.List today is a messy intermediate state: https://ghc.haskell.org/trac/ghc/wiki/Prelude710/FTP#list When and if we get a resolution to https://ghc.haskell.org/trac/ghc/ticket/4879 we're likely to proceed with option 1 from that FTP page, which will at least avoid Data.List.concat having the too general type, by dint of it no longer existing. -Edward On Thu, Mar 2, 2017 at 2:17 PM, Andreas Abel <andreas.abel@ifi.lmu.de> wrote:
We could have a module
Data.List.ReallyJustListsAndNotSomeThingMoreGeneric
which implements concat and friends just for lists and could be imported if one wants to have the list operations. Currently,
import qualified Data.List as List
does not give on the list operations as e.g.
List.concat
but the generic ones.
See also http://ghc.haskell.org/trac/ghc/ticket/13345
On 02.03.2017 20:02, Edward Kmett wrote:
On Thu, Mar 2, 2017 at 11:59 AM, Andreas Abel <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de>> wrote:
Ok, Foldable is a formal condition for Traversable, but not actually used in the implementation of Traversable Either. This still leaves room to implement Foldable for Either by
instance Foldable (Either a) where foldMap _ _ = error "Folding Either? Naah, I don't think this is a good idea."
This would change the semantic of every
forM_ myeither $ \i -> ....
in existing code to silent errors.
Hell no.
-Edward
On 02.03.2017 17:48, David Feuer wrote:
The problem is that we'd then lose the perfectly good Traversable instance, which would be sad.
On Mar 2, 2017 11:23 AM, "Andreas Abel" <andreas.abel@ifi.lmu.de <mailto:andreas.abel@ifi.lmu.de> <mailto:andreas.abel@ifi.lmu.de
<mailto:andreas.abel@ifi.lmu.de>>> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html>
<https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html <https://mail.haskell.org/pipermail/libraries/2016-February/ 026678.html>>
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se <mailto:andreas.abel@gu.se> <mailto:andreas.abel@gu.se <mailto:andreas.abel@gu.se>> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/> <http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~abela/>> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> <mailto:Libraries@haskell.org <mailto:Libraries@haskell.org>> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries> <http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se <mailto:andreas.abel@gu.se> http://www.cse.chalmers.se/~abela/ <http://www.cse.chalmers.se/~a bela/> _______________________________________________ Libraries mailing list Libraries@haskell.org <mailto:Libraries@haskell.org> http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries <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@gu.se http://www.cse.chalmers.se/~abela/
On Thu, 2 Mar 2017, Andreas Abel wrote:
We could have a module
Data.List.ReallyJustListsAndNotSomeThingMoreGeneric
which implements concat and friends just for lists and could be imported if one wants to have the list operations. Currently,
import qualified Data.List as List
does not give on the list operations as e.g.
List.concat
but the generic ones.
I have compiled the package prelude-compat for that purpose: http://hackage.haskell.org/package/prelude-compat
On Thu, Mar 02, 2017 at 05:22:48PM +0100, Andreas Abel wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
I keep making the same mistake when using Parsec to process a file; calling `length` on the result (to check how many thingies I have parsed) returns 1, 1 and again 1, no matter how many times I tinker with the code. I feel such a fool after recognising my misstep, every time.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
I suspect it had no consequences because the mother of all battles was "Foldable and Traversable to become importable unqualified"; and once you set the goal (and reap the benefits: Traversable), you have to live with some of the annoying consequences.
I'm very strongly -1 against deprecating or removing this instance. It removes an instance that is the only possible instance for the type for purely proscriptive reasons. The moment someone needs it they now have to make a new data type with completely identical instances for everything else, but this actively gets in the way of code sharing and reuse. On top of that, using mapM over Either or Maybe is a fairly common idiom today, so the implications would be wide-reaching. -Edward On Thu, Mar 2, 2017 at 11:22 AM, Andreas Abel <andreas.abel@ifi.lmu.de> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se http://www.cse.chalmers.se/~abela/ _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
(This is a reply to this topic in general, not specific to Andreas' suggestion. Also, this argument should generalize well to other Foldable methods/instances.) I don't like the behaviour you observe either. Still the analysis/proposal ignores half of the cause - this has been (at least indirectly) pointed out repeatedly in this and past threads already, but I'd like to state it clearly because people also repeatedly seem to ignore the fact. In order for the expression `concat (xs :: [Either a [b]])` to be accepted, two things need to be the case: Firstly the concat in scope needs to be one that is expressed in terms of Foldable. Secondly there needs to be a Foldable instance for Either. (Technically it needs to be in scope too, but the difference matters only if the instance was an orphan, but I'll assume for now that "orphanization" is not the solution.) The first reason is of course connected to the design of the default Prelude - which I suppose was responsible for getting the specific `concat` into scope here. We could change either of these causes: Change what is exported from Prelude or Remove the instance (and both are breaking compatibility). As a consequence, I find going from "uses of concat(/length/maximum/..) may be confusing/cause bugs" to "we need to remove the instance" to be a weak conclusion. Further, if don't overlook something, removing an instance (or removing a particular method from an instance) always would create at least as much trouble as changing what is exported from the Prelude would, as the types of concat/length/maximum/.. would necessarily change as a consequence of the former. So to all those arguing in favour of removing methods/instances: What does removing/prohibiting instances give in addition to a change to the type of concat(/length/..) as included unqualified in the default Prelude? In this direction, I have not seen any convincing arguments. (And sorry, I have not read all messages in the previous discussions - it was a bit too much to read for too little general enlightenment.) (My solution is to use custom Preludes for personal projects with exclusively qualified imports, e.g. List.length :: [a] -> Int and Foldable.length :: Foldable t => t a -> Int. Works well, but I see the issues that a custom Prelude is yet another hurdle for beginners.) -- lennart On 02/03/17 17:22, Andreas Abel wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
Yes. I completely agree that the goal of being able to import Data.Foldable unqualified was the wrong goal from the start. That goal is sensible for Data.Traversable, I think, since Traversable has very few methods and since instances are sufficiently constrained to prevent *most* of these problems. But it falls apart for Data.Foldable, which is too "wild". I for one would be quite happy to banish the lion's share of Foldable operations back to Data.Foldable, so the Prelude would re-export only Data.Foldable (Foldable (foldMap)), and Data.List would export only list-specific functions. On Fri, Mar 3, 2017 at 10:32 AM, lennart spitzner <lsp@informatik.uni-kiel.de> wrote:
(This is a reply to this topic in general, not specific to Andreas' suggestion. Also, this argument should generalize well to other Foldable methods/instances.)
I don't like the behaviour you observe either. Still the analysis/proposal ignores half of the cause - this has been (at least indirectly) pointed out repeatedly in this and past threads already, but I'd like to state it clearly because people also repeatedly seem to ignore the fact.
In order for the expression `concat (xs :: [Either a [b]])` to be accepted, two things need to be the case: Firstly the concat in scope needs to be one that is expressed in terms of Foldable. Secondly there needs to be a Foldable instance for Either. (Technically it needs to be in scope too, but the difference matters only if the instance was an orphan, but I'll assume for now that "orphanization" is not the solution.) The first reason is of course connected to the design of the default Prelude - which I suppose was responsible for getting the specific `concat` into scope here.
We could change either of these causes: Change what is exported from Prelude or Remove the instance (and both are breaking compatibility). As a consequence, I find going from "uses of concat(/length/maximum/..) may be confusing/cause bugs" to "we need to remove the instance" to be a weak conclusion.
Further, if don't overlook something, removing an instance (or removing a particular method from an instance) always would create at least as much trouble as changing what is exported from the Prelude would, as the types of concat/length/maximum/.. would necessarily change as a consequence of the former. So to all those arguing in favour of removing methods/instances: What does removing/prohibiting instances give in addition to a change to the type of concat(/length/..) as included unqualified in the default Prelude? In this direction, I have not seen any convincing arguments. (And sorry, I have not read all messages in the previous discussions - it was a bit too much to read for too little general enlightenment.)
(My solution is to use custom Preludes for personal projects with exclusively qualified imports, e.g. List.length :: [a] -> Int and Foldable.length :: Foldable t => t a -> Int. Works well, but I see the issues that a custom Prelude is yet another hurdle for beginners.)
-- lennart
On 02/03/17 17:22, Andreas Abel wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
I'd also support this.
El 3 mar 2017, a las 11:23, David Feuer <david.feuer@gmail.com> escribió:
Yes. I completely agree that the goal of being able to import Data.Foldable unqualified was the wrong goal from the start. That goal is sensible for Data.Traversable, I think, since Traversable has very few methods and since instances are sufficiently constrained to prevent *most* of these problems. But it falls apart for Data.Foldable, which is too "wild". I for one would be quite happy to banish the lion's share of Foldable operations back to Data.Foldable, so the Prelude would re-export only Data.Foldable (Foldable (foldMap)), and Data.List would export only list-specific functions.
On Fri, Mar 3, 2017 at 10:32 AM, lennart spitzner <lsp@informatik.uni-kiel.de> wrote:
(This is a reply to this topic in general, not specific to Andreas' suggestion. Also, this argument should generalize well to other Foldable methods/instances.)
I don't like the behaviour you observe either. Still the analysis/proposal ignores half of the cause - this has been (at least indirectly) pointed out repeatedly in this and past threads already, but I'd like to state it clearly because people also repeatedly seem to ignore the fact.
In order for the expression `concat (xs :: [Either a [b]])` to be accepted, two things need to be the case: Firstly the concat in scope needs to be one that is expressed in terms of Foldable. Secondly there needs to be a Foldable instance for Either. (Technically it needs to be in scope too, but the difference matters only if the instance was an orphan, but I'll assume for now that "orphanization" is not the solution.) The first reason is of course connected to the design of the default Prelude - which I suppose was responsible for getting the specific `concat` into scope here.
We could change either of these causes: Change what is exported from Prelude or Remove the instance (and both are breaking compatibility). As a consequence, I find going from "uses of concat(/length/maximum/..) may be confusing/cause bugs" to "we need to remove the instance" to be a weak conclusion.
Further, if don't overlook something, removing an instance (or removing a particular method from an instance) always would create at least as much trouble as changing what is exported from the Prelude would, as the types of concat/length/maximum/.. would necessarily change as a consequence of the former. So to all those arguing in favour of removing methods/instances: What does removing/prohibiting instances give in addition to a change to the type of concat(/length/..) as included unqualified in the default Prelude? In this direction, I have not seen any convincing arguments. (And sorry, I have not read all messages in the previous discussions - it was a bit too much to read for too little general enlightenment.)
(My solution is to use custom Preludes for personal projects with exclusively qualified imports, e.g. List.length :: [a] -> Int and Foldable.length :: Foldable t => t a -> Int. Works well, but I see the issues that a custom Prelude is yet another hurdle for beginners.)
-- lennart
On 02/03/17 17:22, Andreas Abel wrote: Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
On Fri, Mar 3, 2017 at 8:32 AM, lennart spitzner <lsp@informatik.uni-kiel.de
wrote:
(This is a reply to this topic in general, not specific to Andreas' suggestion. Also, this argument should generalize well to other Foldable methods/instances.)
I don't like the behaviour you observe either. Still the analysis/proposal ignores half of the cause - this has been (at least indirectly) pointed out repeatedly in this and past threads already, but I'd like to state it clearly because people also repeatedly seem to ignore the fact.
In order for the expression `concat (xs :: [Either a [b]])` to be accepted, two things need to be the case: Firstly the concat in scope needs to be one that is expressed in terms of Foldable. Secondly there needs to be a Foldable instance for Either. (Technically it needs to be in scope too, but the difference matters only if the instance was an orphan, but I'll assume for now that "orphanization" is not the solution.) The first reason is of course connected to the design of the default Prelude - which I suppose was responsible for getting the specific `concat` into scope here.
I think there's an even more fundamental cause that has been stated implicitly, but not explicitly, in this discussion. Some of us have been continuing the discussion on Twitter, and I want to recapitulate the essential points from that exchange here. In Haskell, Either is the right-biased polymorphic 2-ary sum type; similarly, '(,)' is the snd-biased polymorphic 2-ary product type. These biases are, from my perspective at least, a historical artifact that we're kind of stuck with. @EyalL on Twitter correctly points out that in retrospect, having Either be unbiased, and having a second, biased type with 'Terminate' and 'Continue' constructors might have been the better choice. However, we depend uncritically upon the bias of Either all the time when we >>= it, so objecting to this bias propagating to its being Foldable is inconsistent. I personally depend upon the bias of (,) much less frequently, but I don't assume that gives me any claim to influence others' use of this bias. If, in days of yore, the semantics of Either and (,) had been defined to be unbiased, and separate biased versions been defined, these arguments might have been avoided, and we'd probably see relatively little use of the unbiased Either and predominant use of the unbiased (,). Maybe a new language will some day make this choice with the benefit of hindsight upon the Haskell community's struggles. Kris
I think one of the reasons this debate continues to crop up is that there is a fundamental tension in the design of Haskell: Haskell strives to be a) richly typed, leading to "if it compiles, it works!" b) as general as possible, leading to wide applicability of polymorphic functions These two laudable goals work against each other. In many instances, we will have to choose between them, and different people will have different judgment calls. Perhaps it would bring some of these issues into starker relief if we consider the following instance:
instance Num Bool where (+) = (||) a - b = not (a == b) (*) = (&&)
abs = id signum = id
negate = not
fromInteger 0 = False fromInteger _ = True
This instance is not wholly specious: it's based on well-studied Boolean algebra (at least, the definitions for (+) and (*) are), and it obeys the one documented law for Num instances. It's not fully canonical in the way that, say, the `Foldable ((,) a)` instance is, but not all instances in base are fully canonical, anyway. I venture to say it would find use in practice. But, at the same time, I imagine most Haskellers would find this instance distasteful, as it is too much in service of goal (b) and strays too far from goal (a). About the current debate: my own tendency is to lean toward (a), but the community (now that we have FTP) appears to be drifting more toward (b). Though I see its merits -- and I take advantage of it in my own code -- I've never liked FTP and probably never will. That said, changing Either's Foldable instance to use `error` seems like unnecessary code breakage and goes against the apparent design principles at work in `base`. But, to me, the most important aspect of a debate such as this one is that there is no one right answer, just differing viewpoints, scattered along a spectrum from (a) to (b) (surely among many other axes). We all must live with one `base`, so we all have skin in the game and the debate may be worth continuing. I just hesitate to call any comment I've seen here "wrong". Richard
On Fri, Mar 3, 2017 at 10:37 AM, Richard Eisenberg <rae@cs.brynmawr.edu> wrote:
I think one of the reasons this debate continues to crop up is that there is a fundamental tension in the design of Haskell:
Haskell strives to be a) richly typed, leading to "if it compiles, it works!" b) as general as possible, leading to wide applicability of polymorphic functions
These two laudable goals work against each other. In many instances, we will have to choose between them, and different people will have different judgment calls.
This is an interesting assertion; I don't believe that these goals work against one another at all. In fact, I find that (b) leads to "if it compiles, it works" much more often than not. John De Goes goes into depth on this principle here: http://degoes.net/articles/insufficiently-polymorphic where he points out "Monomorphic code is much more likely to be incorrect than polymorphic code, because for every type signature, there are many more possible implementations.".
On Mar 3, 2017, at 12:45 PM, Kris Nuttycombe <kris.nuttycombe@gmail.com> wrote:
This is an interesting assertion; I don't believe that these goals work against one another at all. In fact, I find that (b) leads to "if it compiles, it works" much more often than not. John De Goes goes into depth on this principle here: http://degoes.net/articles/insufficiently-polymorphic <http://degoes.net/articles/insufficiently-polymorphic> where he points out "Monomorphic code is much more likely to be incorrect than polymorphic code, because for every type signature, there are many more possible implementations.".
Ah -- very good point. This is true for the *implementation* of a polymorphic function, where a polymorphic type signature beautifully restricts what the function can do. But it is not true for monomorphic *uses* of a polymorphic function, where the generality can lead to an unexpected instance selection and thus runtime behavior. Richard
On Fri, Mar 3, 2017 at 10:48 AM, Richard Eisenberg <rae@cs.brynmawr.edu> wrote:
On Mar 3, 2017, at 12:45 PM, Kris Nuttycombe <kris.nuttycombe@gmail.com> wrote:
This is an interesting assertion; I don't believe that these goals work against one another at all. In fact, I find that (b) leads to "if it compiles, it works" much more often than not. John De Goes goes into depth on this principle here: http://degoes.net/articles/insufficiently- polymorphic where he points out "Monomorphic code is much more likely to be incorrect than polymorphic code, because for every type signature, there are many more possible implementations.".
Ah -- very good point. This is true for the *implementation* of a polymorphic function, where a polymorphic type signature beautifully restricts what the function can do. But it is not true for monomorphic *uses* of a polymorphic function, where the generality can lead to an unexpected instance selection and thus runtime behavior.
I guess that, in the limit, this is why my code has been progressively mutating to a style in which I only define data structures for the purpose of being able to easily generate classy lenses/prisms into their components/inhabitants. I now generally find concrete types more restrictive and error-prone than I care for.
But it is not true for ... *uses* of a polymorphic function
Which is confirmed by the present casus. The new highly polymorphic concat is a versatile weapon to shoot yourself in the foot. (However, the weapon designer can sleep even more soundly now in the confidence that his product does not malfunction.) Anyway, for what it's worth, I retreat my proposal (or "proposal"). Sh*t has happened. A monomorphic List library would make sense, though. On 03.03.2017 18:48, Richard Eisenberg wrote:
On Mar 3, 2017, at 12:45 PM, Kris Nuttycombe <kris.nuttycombe@gmail.com <mailto:kris.nuttycombe@gmail.com>> wrote:
This is an interesting assertion; I don't believe that these goals work against one another at all. In fact, I find that (b) leads to "if it compiles, it works" much more often than not. John De Goes goes into depth on this principle here: http://degoes.net/articles/insufficiently-polymorphic where he points out "Monomorphic code is much more likely to be incorrect than polymorphic code, because for every type signature, there are many more possible implementations.".
Ah -- very good point. This is true for the *implementation* of a polymorphic function, where a polymorphic type signature beautifully restricts what the function can do. But it is not true for monomorphic *uses* of a polymorphic function, where the generality can lead to an unexpected instance selection and thus runtime behavior.
Richard
_______________________________________________ Libraries mailing list Libraries@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@gu.se http://www.cse.chalmers.se/~abela/
I am opposed to making this change. I have the same objections that others on this thread do. It's unfortunate that the concat put in scope by the Prelude is the one from Data.Foldable and not the one from GHC.OldList. I do not think that removing Foldable instances is an appropriate solution to this problem though. On Thu, Mar 2, 2017 at 11:22 AM, Andreas Abel <andreas.abel@ifi.lmu.de> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se http://www.cse.chalmers.se/~abela/ _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
-- -Andrew Thaddeus Martin
I am opposed too. Aside from the technical reasons, which have already been discussed and decided, confused students dictating language and library design has never worked out well. On Thu, Mar 9, 2017 at 12:49 PM, Andrew Martin <andrew.thaddeus@gmail.com> wrote:
I am opposed to making this change. I have the same objections that others on this thread do. It's unfortunate that the concat put in scope by the Prelude is the one from Data.Foldable and not the one from GHC.OldList. I do not think that removing Foldable instances is an appropriate solution to this problem though.
On Thu, Mar 2, 2017 at 11:22 AM, Andreas Abel <andreas.abel@ifi.lmu.de> wrote:
Today a student came to me wondering why a certain function produced a regular result, where he had expected an error. Turned out he had used `concat`, but not on a lists of lists as he had thought, but on a lists of `Either a [b]`.
With the Foldable instance for Either, which considers Either a b to be a container of 0-1 elements of b, errors are happily swallowed.
I think this instance is harmful and should be deprecated (and later removed) from base.
There are similarly pointless Foldable instances as well.
See a discussion one year ago, which was heated, but had no consequences.
https://mail.haskell.org/pipermail/libraries/2016-February/026678.html
-- Andreas Abel <>< Du bist der geliebte Mensch.
Department of Computer Science and Engineering Chalmers and Gothenburg University, Sweden
andreas.abel@gu.se http://www.cse.chalmers.se/~abela/ _______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
-- -Andrew Thaddeus Martin
_______________________________________________ Libraries mailing list Libraries@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Hi, Andrew Martin wrote:
Aside from the technical reasons, which have already been discussed and decided, confused students dictating language and library design has never worked out well.
Neither arguing for or against here, but let it just be clear that it is *not* just students who have been bitten by this particular change, but also very experienced Haskellers. And they don't like it a bit. Besides, is there *any* concrete evidence language and library design necessarily must be confusing to students in order to work for real applications? I'd say there is plenty of evidence to the contrary. For example, what effectively is no more than Haskell 98 is used very successfully within Standard Chartered bank, which probably has the largest team of Haskell programmers in the world. And they made a very deliberate, carefully considered choice to keep their in-house version of Haskell simple. Now, I am obviously not arguing to move back to Haskell 98. But I think this example very convincingly demonstrates that conceptual simplicity can go a very long way indeed, and that lots of features and extensions that are seen as very important by some, in the bigger picture perhaps were not so essential after all. And maybe the cost imposed on the rest of the community outweighs their benefit. Best, /Henrik This message and any attachment are intended solely for the addressee and may contain confidential information. If you have received this message in error, please send it back to me, and immediately delete it. Please do not use, copy or disclose the information contained in this message or in any attachment. Any views or opinions expressed by the author of this email do not necessarily reflect the views of the University of Nottingham. This message has been checked for viruses but the contents of an attachment may still contain software viruses which could damage your computer system, you are advised to perform your own checks. Email communications with the University of Nottingham may be monitored as permitted by UK legislation.
participants (24)
-
Adam Bergmark -
amindfv@gmail.com -
Andreas Abel -
Andreas Abel -
Andrew Martin -
Carter Schonwald -
Dan Burton -
David Feuer -
David Menendez -
Edward Kmett -
Francesco Ariis -
Henning Thielemann -
Henrik Nilsson -
Ivan Lazar Miljenovic -
Kris Nuttycombe -
Lana Black -
lennart spitzner -
Matthew Pickering -
Oleg Grenrus -
Oliver Charles -
Richard Eisenberg -
Tom Murphy -
Tony Morris -
Tony Morris