Re: [Haskell-cafe] Foldable for (,)

Look at the Stream functor in Data.Stream [1]. Below I will argue by examples that while both Foldable and Traversable instances can be defined, the Foldable instance is less likely to produce terminating functions. Streams can be given a Traversable instance easily: instance Traversable Stream where sequenceA (Cons fa fas) = liftA2 Cons fa (sequenceA fas) For some applicatives this will not terminate. For streams of Maybes, sequenceA will either yield Just an infinite stream or return Nothing. Streams of IO actions also seem fine. A possible Foldable instance would suffer the same termination issues due to recursion. But with a monoid, folds over a stream will terminate less often, e.g. instance Foldable Stream where foldMap f (Cons x xs) = mappend (f x) (foldMap f xs) Then, all (xs :: Stream Bool) will diverge for the constant True stream and terminate for all others. -- Olaf [1] http://hackage.haskell.org/package/Stream-0.4.7.2/docs/Data-Stream.html

On 03/05/2017, Olaf Klinke
Streams can be given a Traversable instance easily:
instance Traversable Stream where sequenceA (Cons fa fas) = liftA2 Cons fa (sequenceA fas)
For some applicatives this will not terminate. For streams of Maybes, sequenceA will either yield Just an infinite stream or return Nothing.
I believe this will never return `Just` an infinite stream — rather, it will not terminate.

Am 03.05.2017 um 23:20 schrieb M Farkas-Dyck
: On 03/05/2017, Olaf Klinke
wrote: Streams can be given a Traversable instance easily:
instance Traversable Stream where sequenceA (Cons fa fas) = liftA2 Cons fa (sequenceA fas)
For some applicatives this will not terminate. For streams of Maybes, sequenceA will either yield Just an infinite stream or return Nothing.
I believe this will never return `Just` an infinite stream — rather, it will not terminate. Of course you are right, I did not test - the program can only be certain of the Just constructor after knowing that no Nothing occurs in the infinite stream. So perhaps the applicatives where sequenceA terminates and the case where foldMap terminates are the same?
Anyways, Data.Traversable has foldMapDefault. Thus it seems the original argument that ((,) a) must have a Foldable instance because we want the Traversable instance is valid. For the same reason we made Applicative a superclass of Monad. One might hence wonder whether the brevity and convenience bought by the Traversable instance is worth the confusion brought about by the Foldable instance. There are similar cases in the mathematical world. Most mathematicians are happy to use the Axiom of Choice, knowing that accepting it leads to things like the Banach-Tarski Paradox. Then there are constructivists who deny the existence of non-measurable sets (because you need the Axiom of Choice to prove their existence), and the Banach-Tarski Paradox goes away. By this analogy, the Foldable instance of ((,) a) is the Banach-Tarski paradox which we accept and avoid to obtain other nice things we need. Olaf

El 4 may 2017, a las 14:20, Olaf Klinke
escribió:
[...]
Most mathematicians are happy to use the Axiom of Choice, knowing that accepting it leads to things like the Banach-Tarski Paradox. Then there are constructivists who deny the existence of non-measurable sets (because you need the Axiom of Choice to prove their existence), and the Banach-Tarski Paradox goes away. By this analogy, the Foldable instance of ((,) a) is the Banach-Tarski paradox which we accept and avoid to obtain other nice things we need.
This to me is the center of the conversation: we're choosing whether we need the instances badly enough that we tolerate some, ahem, bad behavior. Can you provide specific code examples where you (or others) truly needed those instances to get something done? Tom

This to me is the center of the conversation: we're choosing whether we need the instances badly enough that we tolerate some, ahem, bad behavior.
I dispute that. To me, the center of the disagreement is between two different kinds of consistency: On the one hand, there's the consistency with a view of the world that treats One as a special number different from all other numbers. This view is based on the real world where singularities seem rampant. On the other side is consistency with a math-y view of the world that wants to unify as much as possible so we can reduce the number of models, thus, work. But if you want to treat the cardinality of one specially, do you want to drop Const and Identity, too? Const is closer to tuples than lists are, so why not cut them out as well? But then we had examples in just this conversation where Const and Identity where really useful. What argument is left to remove instances for tuples? If you can get over the 5-second weirdness of Const, why not tuples? At the end I claim there is no bad behavior. I do give you that there is /missing/ behavior because the choice to have only that one instance per tuple size is a bit arbitrary and misleading. And that is hard to change for now. But do you really want to remove those few instances we do have just because we're not ready to include the others yet? MarLinn

My answer this is: because Foldable instances on tuples make Haskell
programming more dangerous.
With all instances, there is some risk of accidental unification with
broken programs. But in general, we are saved by one of two things: either
the types are special-purpose enough that they are unlikely to occur by
accident, or unification just propagates the incorrect type and the
compiler merely puts the error message is in the wrong place.
With length and tuples, though, we're talking about a type that's used
casually in many situations; and the accidental unification does not
propagate the type at all. Instead, it just generates incorrect code.
That's a bit scary!
It's unfortunate that discussions of this tend to get muddied by the
possibility of length having a different meaning on tuples. Really, IMHO,
that's not even related to the problem. The problem is that accidental
unification is more risky here than anywhere other commonly used bit of
Haskell that I can find.
On Thu, May 4, 2017 at 1:32 PM, MarLinn
This to me is the center of the conversation: we're choosing whether we need the instances badly enough that we tolerate some, ahem, bad behavior.
I dispute that. To me, the center of the disagreement is between two different kinds of consistency: On the one hand, there's the consistency with a view of the world that treats One as a special number different from all other numbers. This view is based on the real world where singularities seem rampant. On the other side is consistency with a math-y view of the world that wants to unify as much as possible so we can reduce the number of models, thus, work.
But if you want to treat the cardinality of one specially, do you want to drop Const and Identity, too? Const is closer to tuples than lists are, so why not cut them out as well? But then we had examples in just this conversation where Const and Identity where really useful. What argument is left to remove instances for tuples? If you can get over the 5-second weirdness of Const, why not tuples? At the end I claim there is no bad behavior. I do give you that there is *missing* behavior because the choice to have only that one instance per tuple size is a bit arbitrary and misleading. And that is hard to change for now. But do you really want to remove those few instances we do have just because we're not ready to include the others yet?
MarLinn
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Another factor: Foldable and Traversable are both closed under composition,
meaning that `newtype Compose f g a = Compose (f (g a))` has the following
instances:
instance (Foldable f, Foldable g) => Foldable (Compose f g)
instance (Traversable f, Traversable g) => Traversable (Compose f g)
Removing the Foldable instance for `(,) e` would also remove the Foldable
and Traversable instance for any composition of functors containing tuples.
If you're writing your code in terms of fixed points of type constructors,
then this is a problem.
Matt Parsons
On Thu, May 4, 2017 at 2:52 PM, Chris Smith
My answer this is: because Foldable instances on tuples make Haskell programming more dangerous.
With all instances, there is some risk of accidental unification with broken programs. But in general, we are saved by one of two things: either the types are special-purpose enough that they are unlikely to occur by accident, or unification just propagates the incorrect type and the compiler merely puts the error message is in the wrong place.
With length and tuples, though, we're talking about a type that's used casually in many situations; and the accidental unification does not propagate the type at all. Instead, it just generates incorrect code. That's a bit scary!
It's unfortunate that discussions of this tend to get muddied by the possibility of length having a different meaning on tuples. Really, IMHO, that's not even related to the problem. The problem is that accidental unification is more risky here than anywhere other commonly used bit of Haskell that I can find.
On Thu, May 4, 2017 at 1:32 PM, MarLinn
wrote: This to me is the center of the conversation: we're choosing whether we need the instances badly enough that we tolerate some, ahem, bad behavior.
I dispute that. To me, the center of the disagreement is between two different kinds of consistency: On the one hand, there's the consistency with a view of the world that treats One as a special number different from all other numbers. This view is based on the real world where singularities seem rampant. On the other side is consistency with a math-y view of the world that wants to unify as much as possible so we can reduce the number of models, thus, work.
But if you want to treat the cardinality of one specially, do you want to drop Const and Identity, too? Const is closer to tuples than lists are, so why not cut them out as well? But then we had examples in just this conversation where Const and Identity where really useful. What argument is left to remove instances for tuples? If you can get over the 5-second weirdness of Const, why not tuples? At the end I claim there is no bad behavior. I do give you that there is *missing* behavior because the choice to have only that one instance per tuple size is a bit arbitrary and misleading. And that is hard to change for now. But do you really want to remove those few instances we do have just because we're not ready to include the others yet?
MarLinn
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
participants (6)
-
amindfv@gmail.com
-
Chris Smith
-
M Farkas-Dyck
-
MarLinn
-
Matt
-
Olaf Klinke