
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café: I've seen many threads, including the one going on now, about why we need to have: length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default?

It's Foldable for ((,) a). It is not Foldable for any of these things: * (,) * tuples * pairs In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion. Ask yourself what the length of this value is: [[1,2,3], [4,5,6]] Is it 6? What about this one: [(1, 'a'), (undefined, 77)] Is it 4? No, obviously not, which we can determine by: :kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> * Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside. By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so. On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.

Thank you for your explanation, but I think I'm missing something basic. Lists can have a variable length, so it makes sense to have operations that return the length or operate over a set. As ((,) a) can only have one value, the Foldable operations appear to be redundant as well as misleading (by implying that there could be more than one value).
From: Haskell-Cafe
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
Only members subscribed via the mailman list are allowed to post.

Foldable is required tor datatype to be a Traversable:
class (Functor t, Foldable t) => Traversable (t :: * -> *)
((,) a) is Functor. To be Traversable it has to be Foldable.
If ((,) a) is Traversable then we can write:
sequence (1, Just 2) -- == Just (1,2)
sequence (1, Nothing) -- == Nothing
There could be other useful classes or functions which required Foldable.
An other side, a tuple (with parameterized second part) can be a part of
complex datatype and possibly we need Foldable or Traversable instance for
that type.
If someone inhabits to think about tuple as a Functor, he/she can think
about tuple as Foldable and Traversable as well:
fmap (+1) (1,2) == (1,3)
foldMap (+1) (1,2) == 3
There are other datatypes with similar Foldable instances. I mean a least
Identity.
length (Identity [1,2,3]) == 1
2017-05-03 11:41 GMT+03:00 Jonathon Delgado
Thank you for your explanation, but I think I'm missing something basic. Lists can have a variable length, so it makes sense to have operations that return the length or operate over a set. As ((,) a) can only have one value, the Foldable operations appear to be redundant as well as misleading (by implying that there could be more than one value).
From: Haskell-Cafe
on behalf of Tony Morris Sent: 03 May 2017 08:32 To: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) It's Foldable for ((,) a).
It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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.

A different way to think about it is this: Given any kind of n-tuples that is already filled at any set of n-1 places, there are unique instances for the whole hierarchy (from Functor up to Traversable). For example there is – theoretically – a hierarchy of instances for the tuples (a,b,_,c,d,e). Why isn't it defined? Because 1., we let ourselves be restrained by the linearity of text that "forces" us to define instances in terms of an arbitrary choice of order of arguments. 2., because the longer the tuples, the less we need it, and 3., because it's easier to wing it for the small tuples than to change the language. Also 4., in practice, lens. On 2017-05-03 10:41, Jonathon Delgado wrote:
Thank you for your explanation, but I think I'm missing something basic. Lists can have a variable length, so it makes sense to have operations that return the length or operate over a set. As ((,) a) can only have one value, the Foldable operations appear to be redundant as well as misleading (by implying that there could be more than one value).
From: Haskell-Cafe
on behalf of Tony Morris Sent: 03 May 2017 08:32 To: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) It's Foldable for ((,) a).
It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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.

I'm also interested in Jonathon's question, so let me try to bring things
back to the question. Everyone agrees that there's only one reasonable way
to define this instance if it exists. But the question is: why is it
defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But
I am having trouble giving a simple or accessible answer for Foldable. Do
you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
It's Foldable for ((,) a).
It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.

Replying to myself, I suppose one good answer is that whether or not you
care about Foldable instances for tuples, you might care about Traversable
instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be
happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a).
It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.

Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor?
My background, as you can probably guess, is beginner.
From: Haskell-Cafe
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.

So, suppose I have a function:
f :: a -> IO b
and I need a function of the related type:
(SideValue, a) -> IO (SideValue, b)
Here, SideValue is some kind of state that I am manually threading through
a bunch of computations. For instance, maybe I'm counting steps in a
computation, and SideValue = Int. Whatever. In the particular case of
`f`, I don't actually want to use it at all, because maybe `f` doesn't have
any steps that need to be counted. But in general, maybe I'll be combining
`f` with a bunch of other computations that *do* count steps. Maybe I have
a list of such functions, and I want to add `f` into that list. Before I
can do that, I need to get `f` into the right form, so I can compose it
cleanly with everything else.
I could use a combination of pattern matching and fmap, like this (using
the TupleSections extension for convenience):
\ (s, x) -> fmap (s,) (f x)
But it's just a little cleaner to write this instead:
traverse f
Does that make sense?
On Wed, May 3, 2017 at 2:12 AM, Jonathon Delgado
Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor?
My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Chris Smith Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.
_______________________________________________ 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.

With fmap you can only change all values in some "container". With Foldable you can "fold" it, i.e. calculate some "scalar" result. With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor?
My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Chris Smith Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.
_______________________________________________ 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.

OK, I understand why Traversable is useful here - thank you Chris and Dmitry!
The next question is why Traversable requires Foldable. I looked at the source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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. _______________________________________________ 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.

Look how instance for List is defined.
instance Traversable https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... [] where {-# INLINE traverse #-} -- so that traverse can fuse traverse https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... f https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... = List.foldr https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#fold... cons_f https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... (pure https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#pure []) where cons_f https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... x https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... ys https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... = (:) <$> https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Functor.html#... f https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... x https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h... <*> https://hackage.haskell.org/package/base-4.9.1.0/docs/src/GHC.Base.html#%3C%... ys https://hackage.haskell.org/package/base-4.9.1.0/docs/src/Data.Traversable.h...
It uses List.foldr. Many other instances do the same.
Functions in all instances of class should have the same signatures.
So we have to add Foldable constraint to the class.
Of cause we can implement 'foldr' internaly in 'traverse' if needed
(as well as fmap).
But this is not so good and more important that in this case we don't
know how to derive Traversable instances automatically.
So the answer - many instances wouldn't compile and DeriveTraversable
wouldn't work.
2017-05-03 12:56 GMT+03:00 Jonathon Delgado
OK, I understand why Traversable is useful here - thank you Chris and Dmitry!
The next question is why Traversable requires Foldable. I looked at the source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor? My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Chris Smith Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.
_______________________________________________ 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.

List.foldr has signature (a -> b -> b) -> b -> [a] -> b, i.e. an actual list? How is this effected by the Foldable constraint?
From: Dmitry Olshansky
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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. _______________________________________________ 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.

https://i.imgur.com/A2enuhq.png On 03/05/17 21:17, Jonathon Delgado wrote:
List.foldr has signature (a -> b -> b) -> b -> [a] -> b, i.e. an actual list? How is this effected by the Foldable constraint?
From: Dmitry Olshansky
Sent: 03 May 2017 10:47 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Look how instance for List is defined.
instance Traversable [] where {-# INLINE traverse #-} -- so that traverse can fuse traverse f = List.foldr cons_f (pure []) where cons_f x ys = (:) <$> f x <*> ys It uses List.foldr. Many other instances do the same. Functions in all instances of class should have the same signatures. So we have to add Foldable constraint to the class. Of cause we can implement 'foldr' internaly in 'traverse' if needed (as well as fmap). But this is not so good and more important that in this case we don't know how to derive Traversable instances automatically.
So the answer - many instances wouldn't compile and DeriveTraversable wouldn't work.
2017-05-03 12:56 GMT+03:00 Jonathon Delgado
: OK, I understand why Traversable is useful here - thank you Chris and Dmitry! The next question is why Traversable requires Foldable. I looked at the source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,)
With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor? My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Chris Smith Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.
_______________________________________________ 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.
_______________________________________________ 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.

Interesting, that's not the one linked to from Dmitry's code.
In any case, is this correct?
1) Traversable is useful for all containers, including ones which can only hold a single value, such as (,) a.
2) The traversable definition for containers which can hold multiple versions requires Foldable.
3) So Traversable has to depend on Foldable.
4) So singleton containers also have to implement Foldable, even when it doesn't really make sense to do so.
Is there some kind of refactoring which would "fix" this, other than two unrelated Traversable classes? I understand that it might be impractical to refactor a widely-used standard library, but I would be interested in how such a situation could be avoided when starting from scratch.
From: Haskell-Cafe
List.foldr has signature (a -> b -> b) -> b -> [a] -> b, i.e. an actual list? How is this effected by the Foldable constraint?
From: Dmitry Olshansky
Sent: 03 May 2017 10:47 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Look how instance for List is defined.
instance Traversable [] where {-# INLINE traverse #-} -- so that traverse can fuse traverse f = List.foldr cons_f (pure []) where cons_f x ys = (:) <$> f x <*> ys It uses List.foldr. Many other instances do the same. Functions in all instances of class should have the same signatures. So we have to add Foldable constraint to the class. Of cause we can implement 'foldr' internaly in 'traverse' if needed (as well as fmap). But this is not so good and more important that in this case we don't know how to derive Traversable instances automatically.
So the answer - many instances wouldn't compile and DeriveTraversable wouldn't work.
2017-05-03 12:56 GMT+03:00 Jonathon Delgado
: OK, I understand why Traversable is useful here - thank you Chris and Dmitry! The next question is why Traversable requires Foldable. I looked at the source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,)
With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor? My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Chris Smith Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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.
_______________________________________________ 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.

Traversable instances (for "singletons" or not) can be implemented _uniformly_ using Functor and Foldable instances. And they are implemented in such way when you derive Traversable. So we need Foldable constraint for the class. E.g. {-# LANGUAGE DeriveFunctor, DeriveFoldable,DeriveTraversable #-}
data D a = D { f1 :: [a], f2 :: (String, a) } deriving (Show, Eq, Functor, Foldable, Traversable) sum $ D [1..3] ("test",4) 10 mapM_ print $ sequenceA $ D [[1,2],[3,4]] ("test",[5,6]) D {f1 = [1,3], f2 = ("test",5)} D {f1 = [1,3], f2 = ("test",6)} D {f1 = [1,4], f2 = ("test",5)} D {f1 = [1,4], f2 = ("test",6)} D {f1 = [2,3], f2 = ("test",5)} D {f1 = [2,3], f2 = ("test",6)} D {f1 = [2,4], f2 = ("test",5)} D {f1 = [2,4], f2 = ("test",6)}
2017-05-03 14:34 GMT+03:00 Jonathon Delgado
Interesting, that's not the one linked to from Dmitry's code.
In any case, is this correct?
1) Traversable is useful for all containers, including ones which can only hold a single value, such as (,) a. 2) The traversable definition for containers which can hold multiple versions requires Foldable. 3) So Traversable has to depend on Foldable. 4) So singleton containers also have to implement Foldable, even when it doesn't really make sense to do so.
Is there some kind of refactoring which would "fix" this, other than two unrelated Traversable classes? I understand that it might be impractical to refactor a widely-used standard library, but I would be interested in how such a situation could be avoided when starting from scratch.
From: Haskell-Cafe
on behalf of Tony Morris Sent: 03 May 2017 11:21 To: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) https://i.imgur.com/A2enuhq.png
List.foldr has signature (a -> b -> b) -> b -> [a] -> b, i.e. an actual
On 03/05/17 21:17, Jonathon Delgado wrote: list? How is this effected by the Foldable constraint?
From: Dmitry Olshansky
Sent: 03 May 2017 10:47 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Look how instance for List is defined.
instance Traversable [] where {-# INLINE traverse #-} -- so that
Functions in all instances of class should have the same signatures. So we have to add Foldable constraint to the class. Of cause we can implement 'foldr' internaly in 'traverse' if needed (as well as fmap). But this is not so good and more important that in this case we don't know how to derive Traversable instances automatically.
So the answer - many instances wouldn't compile and DeriveTraversable wouldn't work.
2017-05-03 12:56 GMT+03:00 Jonathon Delgado
: OK, I understand why Traversable is useful here - thank you Chris and Dmitry! The next question is why Traversable requires Foldable. I looked at the
traverse can fuse traverse f = List.foldr cons_f (pure []) where cons_f x ys = (:) <$> f x <*> ys It uses List.foldr. Many other instances do the same. source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,)
With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor?
My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,)
Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring
Chris Smith
things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all? That's an easy question to answer for Functor, Applicative, and Monad.
But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote:
It's Foldable for ((,) a).
It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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.
_______________________________________________ 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.
https://i.imgur.com/A2enuhq.png
_______________________________________________ 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.

To me, the fact that DeriveTraversable requires a Foldable instance is not an argument saying that Foldable needs to be a superclass of Traversable. It just restricts the usefulness of DeriveTraversable. We could always advertise that DeriveTraversable works only on types with Foldable instances -- no need to bake this restriction into the superclass constraints of Traversable. To be clear, I'm *not* arguing that Foldable shouldn't be a superclass of Traversable. I'm not knowledgeable enough on the specifics to make that claim. I *am* arguing that support for DeriveTraversable doesn't seem to a great argument for putting Foldable as a superclass of Traversable, though. Richard
On May 3, 2017, at 10:38 AM, Dmitry Olshansky
wrote: Traversable instances (for "singletons" or not) can be implemented _uniformly_ using Functor and Foldable instances. And they are implemented in such way when you derive Traversable. So we need Foldable constraint for the class.
E.g. {-# LANGUAGE DeriveFunctor, DeriveFoldable,DeriveTraversable #-}
data D a = D { f1 :: [a], f2 :: (String, a) } deriving (Show, Eq, Functor, Foldable, Traversable) sum $ D [1..3] ("test",4) 10 mapM_ print $ sequenceA $ D [[1,2],[3,4]] ("test",[5,6]) D {f1 = [1,3], f2 = ("test",5)} D {f1 = [1,3], f2 = ("test",6)} D {f1 = [1,4], f2 = ("test",5)} D {f1 = [1,4], f2 = ("test",6)} D {f1 = [2,3], f2 = ("test",5)} D {f1 = [2,3], f2 = ("test",6)} D {f1 = [2,4], f2 = ("test",5)} D {f1 = [2,4], f2 = ("test",6)}
2017-05-03 14:34 GMT+03:00 Jonathon Delgado
mailto:voldermort@hotmail.com>: Interesting, that's not the one linked to from Dmitry's code. In any case, is this correct?
1) Traversable is useful for all containers, including ones which can only hold a single value, such as (,) a. 2) The traversable definition for containers which can hold multiple versions requires Foldable. 3) So Traversable has to depend on Foldable. 4) So singleton containers also have to implement Foldable, even when it doesn't really make sense to do so.
Is there some kind of refactoring which would "fix" this, other than two unrelated Traversable classes? I understand that it might be impractical to refactor a widely-used standard library, but I would be interested in how such a situation could be avoided when starting from scratch.
From: Haskell-Cafe
mailto:haskell-cafe-bounces@haskell.org> on behalf of Tony Morris mailto:tonymorris@gmail.com> Sent: 03 May 2017 11:21 To: haskell-cafe@haskell.org mailto:haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) https://i.imgur.com/A2enuhq.png https://i.imgur.com/A2enuhq.png
On 03/05/17 21:17, Jonathon Delgado wrote:
List.foldr has signature (a -> b -> b) -> b -> [a] -> b, i.e. an actual list? How is this effected by the Foldable constraint?
From: Dmitry Olshansky
mailto:olshanskydr@gmail.com> Sent: 03 May 2017 10:47 To: Jonathon Delgado Cc: haskell-cafe@haskell.org mailto:haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Look how instance for List is defined.
instance Traversable [] where {-# INLINE traverse #-} -- so that traverse can fuse traverse f = List.foldr cons_f (pure []) where cons_f x ys = (:) <$> f x <*> ys It uses List.foldr. Many other instances do the same. Functions in all instances of class should have the same signatures. So we have to add Foldable constraint to the class. Of cause we can implement 'foldr' internaly in 'traverse' if needed (as well as fmap). But this is not so good and more important that in this case we don't know how to derive Traversable instances automatically.
So the answer - many instances wouldn't compile and DeriveTraversable wouldn't work.
2017-05-03 12:56 GMT+03:00 Jonathon Delgado
mailto:voldermort@hotmail.com>: OK, I understand why Traversable is useful here - thank you Chris and Dmitry! The next question is why Traversable requires Foldable. I looked at the source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
mailto:olshanskydr@gmail.com> Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org mailto:haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,)
With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
mailto:voldermort@hotmail.com>: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor? My background, as you can probably guess, is beginner.
From: Haskell-Cafe
mailto:haskell-cafe-bounces@haskell.org> on behalf of Chris Smith mailto:cdsmith@gmail.com> Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org mailto:haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
mailto:cdsmith@gmail.com> wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
mailto:tonymorris@gmail.com> wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org http://mail.haskell.org/ This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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 http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org http://mail.haskell.org/ This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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 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 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 http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.
https://i.imgur.com/A2enuhq.png https://i.imgur.com/A2enuhq.png
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe 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.

Hmm, you are right! My objections were invalid.
So I don't know an answer... Really, why we have this constraint? The same
question is about Functor.
2017-05-03 17:43 GMT+03:00 Richard Eisenberg
To me, the fact that DeriveTraversable requires a Foldable instance is not an argument saying that Foldable needs to be a superclass of Traversable. It just restricts the usefulness of DeriveTraversable. We could always advertise that DeriveTraversable works only on types with Foldable instances -- no need to bake this restriction into the superclass constraints of Traversable.
To be clear, I'm *not* arguing that Foldable shouldn't be a superclass of Traversable. I'm not knowledgeable enough on the specifics to make that claim. I *am* arguing that support for DeriveTraversable doesn't seem to a great argument for putting Foldable as a superclass of Traversable, though.
Richard
On May 3, 2017, at 10:38 AM, Dmitry Olshansky
wrote: Traversable instances (for "singletons" or not) can be implemented _uniformly_ using Functor and Foldable instances. And they are implemented in such way when you derive Traversable. So we need Foldable constraint for the class.
E.g. {-# LANGUAGE DeriveFunctor, DeriveFoldable,DeriveTraversable #-}
data D a = D { f1 :: [a], f2 :: (String, a) } deriving (Show, Eq, Functor, Foldable, Traversable) sum $ D [1..3] ("test",4) 10 mapM_ print $ sequenceA $ D [[1,2],[3,4]] ("test",[5,6]) D {f1 = [1,3], f2 = ("test",5)} D {f1 = [1,3], f2 = ("test",6)} D {f1 = [1,4], f2 = ("test",5)} D {f1 = [1,4], f2 = ("test",6)} D {f1 = [2,3], f2 = ("test",5)} D {f1 = [2,3], f2 = ("test",6)} D {f1 = [2,4], f2 = ("test",5)} D {f1 = [2,4], f2 = ("test",6)}
2017-05-03 14:34 GMT+03:00 Jonathon Delgado
: Interesting, that's not the one linked to from Dmitry's code.
In any case, is this correct?
1) Traversable is useful for all containers, including ones which can only hold a single value, such as (,) a. 2) The traversable definition for containers which can hold multiple versions requires Foldable. 3) So Traversable has to depend on Foldable. 4) So singleton containers also have to implement Foldable, even when it doesn't really make sense to do so.
Is there some kind of refactoring which would "fix" this, other than two unrelated Traversable classes? I understand that it might be impractical to refactor a widely-used standard library, but I would be interested in how such a situation could be avoided when starting from scratch.
From: Haskell-Cafe
on behalf of Tony Morris Sent: 03 May 2017 11:21 To: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) https://i.imgur.com/A2enuhq.png
List.foldr has signature (a -> b -> b) -> b -> [a] -> b, i.e. an actual
On 03/05/17 21:17, Jonathon Delgado wrote: list? How is this effected by the Foldable constraint?
From: Dmitry Olshansky
Sent: 03 May 2017 10:47 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Look how instance for List is defined.
instance Traversable [] where {-# INLINE traverse #-} -- so that
Functions in all instances of class should have the same signatures. So we have to add Foldable constraint to the class. Of cause we can implement 'foldr' internaly in 'traverse' if needed (as well as fmap). But this is not so good and more important that in this case we don't know how to derive Traversable instances automatically.
So the answer - many instances wouldn't compile and DeriveTraversable wouldn't work.
2017-05-03 12:56 GMT+03:00 Jonathon Delgado
: OK, I understand why Traversable is useful here - thank you Chris and Dmitry! The next question is why Traversable requires Foldable. I looked at the
traverse can fuse traverse f = List.foldr cons_f (pure []) where cons_f x ys = (:) <$> f x <*> ys It uses List.foldr. Many other instances do the same. source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,)
With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor?
My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,)
Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring
Chris Smith
things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all? That's an easy question to answer for Functor, Applicative, and Monad.
But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote:
It's Foldable for ((,) a).
It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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
Haskell-Cafe Info Page mail.haskell.org This mailing list is for the discussion of topics related to Haskell. The volume may at times be high, as the scope is broader than the main Haskell mailing list.
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.
_______________________________________________ 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.
https://i.imgur.com/A2enuhq.png
_______________________________________________ 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.
_______________________________________________ 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.

It's a nice challenge to come up with datatypes that could be Traversable but not Foldable. First of all, you can think of Traversable as an extension of Functor. Instead of only mapping over the structure with a pure function, you can now also map over it with a "functorial function" (a -> f b) (I don't know of a better name, so I'm inventing one.) What that means is to have a Traversable structure, you need to have the ability to touch every element. If you can touch every element, why would you not be able to feed them all into a folding function? Only a few possible anwers come to mind for me: 1. There might be no obvious ordering. But in practice, you just invent one. 2. The structure might be infinite, so folding would never succeed. But laziness ftw. 3. Generalizing the previous answer, the structure might be computed ad-hoc and contain fixed points. That alone might not suffice, but it sounds like a more interesting starting point. 4. Generalizing a bit differently, the structure might be computed ad-hoc… because it's IO. IO surely can't be Foldable. But could it be Traversable? Well… no actually, because order is important. So can you come up with a structure that is computed ad-hoc, that contains fixed points, and where ordering is unimportant? Good luck. Cheers. On 2017-05-03 11:56, Jonathon Delgado wrote:
OK, I understand why Traversable is useful here - thank you Chris and Dmitry!
The next question is why Traversable requires Foldable. I looked at the source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]] [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] sequenceA ("test",[2,3,4]) [("test",2),("test",3),("test",4)] sequenceA ("test",([1,2,3],[4,5,6])) ([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor? My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Chris Smith Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.
_______________________________________________ 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.

It's also interesting, though, to distinguish between two questions. You
are asking whether the Foldable superclass *costs* anything. Others are
asking whether it *adds* anything.
It seems likely, as you say, that the Foldable superclass doesn't cost us
any possible Traversable instances. You can probably demonstrate this by
implementing foldMap in terms of traverse and some Applicative that lets
you accumulate state. (ST? That would definitely work, but feels like
driving in a nail with a sledgehammer.) But the superclass does force
Foldable on tuples, which has cost quite a bit in the long run!
So what is on the benefits side of the balance? I'm very interested in
this. Possible answers that I see are. If a substantial number of uses of
Traversable also require Foldable, then it makes them more concise. But I
am not at all sure that's the case.
One interesting case here is mapM versus mapM_. The former requires
Traversable, but the latter is implementable from just Foldable. It would
be a shame if you could use mapM with some types, but not mapM_.
On Wed, May 3, 2017 at 4:56 AM, MarLinn
It's a nice challenge to come up with datatypes that could be Traversable but not Foldable.
First of all, you can think of Traversable as an extension of Functor. Instead of only mapping over the structure with a pure function, you can now also map over it with a "functorial function" (a -> f b) (I don't know of a better name, so I'm inventing one.) What that means is to have a Traversable structure, you need to have the ability to touch every element. If you can touch every element, why would you not be able to feed them all into a folding function?
Only a few possible anwers come to mind for me:
1. There might be no obvious ordering. But in practice, you just invent one. 2. The structure might be infinite, so folding would never succeed. But laziness ftw. 3. Generalizing the previous answer, the structure might be computed ad-hoc and contain fixed points. That alone might not suffice, but it sounds like a more interesting starting point. 4. Generalizing a bit differently, the structure might be computed ad-hoc… because it's IO. IO surely can't be Foldable. But could it be Traversable? Well… no actually, because order is important.
So can you come up with a structure that is computed ad-hoc, that contains fixed points, and where ordering is unimportant? Good luck.
Cheers.
On 2017-05-03 11:56, Jonathon Delgado wrote:
OK, I understand why Traversable is useful here - thank you Chris and Dmitry!
The next question is why Traversable requires Foldable. I looked at the source, and couldn't see where Foldable is being used, other than as a constraint on Traversable. To put the question differently, what would fail to compile if this constraint was removed?
From: Dmitry Olshansky
Sent: 03 May 2017 09:53 To: Jonathon Delgado Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) With fmap you can only change all values in some "container".
With Foldable you can "fold" it, i.e. calculate some "scalar" result.
With Traversable you can "change order of two containers":
sequenceA [[1,2,3],[4,5]]
[[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
sequenceA ("test",[2,3,4])
[("test",2),("test",3),("test",4)]
sequenceA ("test",([1,2,3],[4,5,6]))
([1,2,3],("test",[4,5,6]))
2017-05-03 12:12 GMT+03:00 Jonathon Delgado
: Why do you want to traverse a tuple instead of fmap? i.e. what can you do with Foldable/Traversable for (,) that you can't do with Functor? My background, as you can probably guess, is beginner.
From: Haskell-Cafe
on behalf of Chris Smith Sent: 03 May 2017 08:51 To: Tony Morris Cc: haskell-cafe@haskell.org Subject: Re: [Haskell-cafe] Foldable for (,) Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a). It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.
_______________________________________________ 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.
_______________________________________________ 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.

What we have here is a feature interaction problem. There's a combination of features (Foldable, Traversable, ((,) a), &c) each of which is sensible and useful, but which together give people a nasty surprise. We also have the combination of a language which is getting a lot of attention in terms of expressiveness, mathematical power, consistency and all manner of goodness BUT less attention with respect to beginners and bears of very little brain like me. If I write something that evaluates to length (2,3), it will quite definitely be unintentional. I'm reminded of a feature that Emacs used to have (and maybe still does): there were lots of commands that beginners were much more likely to type by accident than on purpose, so when you typed on, it would tell you something like "you just typed Ctrl-Meta-Explode, which does XYZ, are you sure you meant to do that?" and if you said yes, it remembered that and would let you use it again. That's one way to try to combine power for experts with safety for beginners. Again, if I remember correctly, PLT Scheme (now Racket) had similar support for beginners, where you could choose different language levels so that beginners didn't have to worry about major or even minor arcana. What I'm wondering here is if there's room in the Haskell world for something similar? Perhaps some sort of Profile: <profile name> pragma, where profiles can say things like "tuples are not Foldable". Does everyone have "beginner" days, or is it just me?

El 3 may 2017, a las 17:58, Richard A. O'Keefe
escribió: What we have here is a feature interaction problem. There's a combination of features (Foldable, Traversable, ((,) a), &c) each of which is sensible and useful, but which together give people a nasty surprise.
We also have the combination of a language which is getting a lot of attention in terms of expressiveness, mathematical power, consistency and all manner of goodness BUT less attention with respect to beginners and bears of very little brain like me.
If I write something that evaluates to length (2,3), it will quite definitely be unintentional. I'm reminded of a feature that Emacs used to have (and maybe still does): there were lots of commands that beginners were much more likely to type by accident than on purpose, so when you typed on, it would tell you something like "you just typed Ctrl-Meta-Explode, which does XYZ, are you sure you meant to do that?" and if you said yes, it remembered that and would let you use it again. That's one way to try to combine power for experts with safety for beginners. Again, if I remember correctly, PLT Scheme (now Racket) had similar support for beginners, where you could choose different language levels so that beginners didn't have to worry about major or even minor arcana.
What I'm wondering here is if there's room in the Haskell world for something similar? Perhaps some sort of Profile: <profile name> pragma, where profiles can say things like "tuples are not Foldable".
Does everyone have "beginner" days, or is it just me?
I find that when people write code as teams, on deadlines, they tend to hit every problem - beginner or not - that there's no protection against. Another potentially-interesting angle to look at this from is security: how easy is it to write innocent-looking code which does something unexpected? Tom
_______________________________________________ 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.

It seems that Traversable is doing two things: 1) Changing the shape of a data structure. 2) Folding over the contents of a data structure. Traversable requires Foldable to enable 2, but Traversable is also applied to types such as (,) where only 1 is relevant. If this is correct, follow-up questions would be: 1) For educational purposes, could these concerns be split without substantial drawback? 2) For practical purposes, could this be done without breaking a lot of existing code?

The relation between Foldable and Traversable is similar to the one between
Applicative and Monad: Traversable does not require Foldable, but every
Traversable has a Foldable instance (given by foldMalDefault). That's why
there is the superclass constraint.
Jonathon Delgado
It seems that Traversable is doing two things:
1) Changing the shape of a data structure. 2) Folding over the contents of a data structure.
Traversable requires Foldable to enable 2, but Traversable is also applied to types such as (,) where only 1 is relevant.
If this is correct, follow-up questions would be:
1) For educational purposes, could these concerns be split without substantial drawback? 2) For practical purposes, could this be done without breaking a lot of existing code? _______________________________________________ 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.

Hi Jonathon,
Traversable instances do not change the shape of a data structure!
On the contrary, the whole purpose of traverse is to combine effectful
computations, stored in a structure without changing its shape! While
Foldable folds over the contents of a data structure (via Monoid),
Traversable allows you to fold over the effects attached to the contents of
that structure (via Applicative).
It turns out that by using Const applicative functor you can use traverse
to perform foldMap! Thus every Traversable is trivially a Foldable (see
foldMapDefault).
Similarly, every Traversable is trivially a Functor if you use Identity
applicative functor (see fmapDefault).
This is why Traversable has those Functor and Foldable constraints, not
because it relies on fmap or foldMap.
Kind regards,
Nick
On Thu, 4 May 2017 at 10:49 Jonathon Delgado
It seems that Traversable is doing two things:
1) Changing the shape of a data structure. 2) Folding over the contents of a data structure.
Traversable requires Foldable to enable 2, but Traversable is also applied to types such as (,) where only 1 is relevant.
If this is correct, follow-up questions would be:
1) For educational purposes, could these concerns be split without substantial drawback? 2) For practical purposes, could this be done without breaking a lot of existing code? _______________________________________________ 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.

Ay, there's the rub. Traversable over (,) can be expressed as a fold over a single element, but that doesn't mean it should be. All you want in this case is the effect.
From: Nickolay Kudasov

An alternate question might be, why is length a class member and not simply
a function? The instance itself is merely documentation of a mathematical
fact; it's only a few members of that instance (which are never part of its
minimum definition!) that seem confusing.
I'm sure the answer to that involves optimizations available for particular
structures, case in point for tuples:
length = const 1
But it's worth understanding it in detail, probably.
On Wed, May 3, 2017 at 1:51 AM, Chris Smith
Replying to myself, I suppose one good answer is that whether or not you care about Foldable instances for tuples, you might care about Traversable instances, and those require Foldable as a superclass.
For example, one possible specialization of `traverse` is:
traverse :: (a -> IO b) -> (SideValue, a) -> IO (SideValue, b)
Jonathon, I don't know how much background you're coming from, so I'd be happy to explain that in more detail if you need it.
On Wed, May 3, 2017 at 1:44 AM, Chris Smith
wrote: I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
That's an easy question to answer for Functor, Applicative, and Monad. But I am having trouble giving a simple or accessible answer for Foldable. Do you know one?
On Wed, May 3, 2017 at 1:32 AM, Tony Morris
wrote: It's Foldable for ((,) a).
It is not Foldable for any of these things:
* (,) * tuples * pairs
In fact, to talk about a Foldable for (,) or "tuples" is itself a kind error. There is no good English name for the type constructor ((,) a) which I suspect, along with being unfamiliar with utilising the practical purpose of types (and types of types) is the root cause of all the confusion in this discussion.
Ask yourself what the length of this value is:
[[1,2,3], [4,5,6]]
Is it 6? What about this one:
[(1, 'a'), (undefined, 77)]
Is it 4? No, obviously not, which we can determine by:
:kind Foldable :: (* -> *) -> Constraint :kind [] :: * -> *
Therefore, there is no possible way that the Foldable instance for [] can inspect the elements (and determine that they are pairs in this case). By this method, we conclude that the length of the value is 2. It cannot be anything else, some assumptions about length itself put aside.
By this ubiquitous and very practical method of reasoning, the length of any ((,) a) is not only one, but very obviously so.
On 03/05/17 17:21, Jonathon Delgado wrote:
I sent the following post to the Beginners list a couple of weeks ago (which failed to furnish an actual concrete example that answered the question). Upon request I'm reposting it to Café:
I've seen many threads, including the one going on now, about why we need to have:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
but the justifications all go over my head. Is there a beginner-friendly explanation for why such seemingly unintuitive operations should be allowed by default? _______________________________________________ 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.
_______________________________________________ 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.

On 05/03/2017 04:44 AM, Chris Smith wrote:
I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
`const 42` is an equally-reasonable implementation to me. If the output is nonsense, who cares what particular nonsense it is? These are all objectively stupid results: length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False Of course you can make up some reasoning that will result in that behavior. For example, * the type ((,) a) must be Traversable * all Traversables should be Foldables * the "length" function should work on Foldables * `const 1` is a fine implementation of length .. etc. (Those are by no means the only assumptions that would lead to the same results.) But normally, when you have a set of assumptions that result in garbage, you don't just shrug and try to convince yourself that maybe the conclusions aren't so bad after all. The point of the type system is not to put stupid behavior on solid theoretical grounds; it's to reject incorrect programs, and "length (2,3)" is an incorrect program. By analogy, ask the same question about, say, PHP. Question: why is "foo" == TRUE in PHP? Answer: it makes perfect sense, once you understand blah blah herp derp. No, it's stupid, and your reasoning is stupid if you can justify it.

On May 3, 2017 at 11:36:00 AM, Michael Orlitzky (michael@orlitzky.com) wrote:
On 05/03/2017 04:44 AM, Chris Smith wrote:
I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
`const 42` is an equally-reasonable implementation to me. If the output is nonsense, who cares what particular nonsense it is?
These are all objectively stupid results:
By analogy, ask the same question about, say, PHP.
Question: why is "foo" == TRUE in PHP? Answer: it makes perfect sense, once you understand blah blah herp derp.
No, it's stupid, and your reasoning is stupid if you can justify it.
We’ve had some discussions about civility lately. This is also about having a productive discussion as well, I think. Comments like the above don’t meaningfully contribute to the discussion, and while they call “results” “objectively stupid” and not people, they tend to raise the temperature of a discussion in such a way that the latter seems only a few more flamewar posts away. I know people have deeply held opinions on things, but simply calling things “objectively stupid” repeatedly and loudly isn’t going to change any of those opinions. We know it won’t do that, because it hasn’t done that for the last two (?) years already. What we know it does, after experiencing it for the past two-ish years, is just make everyone sick of the mailinglists and increasingly testy towards one another, which is an outcome I think nobody wants. Can we stop with this, please? —Gershom

This is probably twentieth time this question arises. Discussion quickly
boils down to people liking convenient syntax sugar Foldable instance gives
(traverse pair, etc), versus people who don't like absurd semantic which
becomes correct with such instances.
Personally, I'm in the second camp, but Foldable instance isn't going
anywhere. But alternative Prelude is always the option.
On Wed, May 3, 2017 at 11:37 AM Michael Orlitzky
On 05/03/2017 04:44 AM, Chris Smith wrote:
I'm also interested in Jonathon's question, so let me try to bring things back to the question. Everyone agrees that there's only one reasonable way to define this instance if it exists. But the question is: why is it defined at all?
`const 42` is an equally-reasonable implementation to me. If the output is nonsense, who cares what particular nonsense it is?
These are all objectively stupid results:
length (2,3) = 1 product (2,3) = 3 sum (2,3) = 3 or (True,False) = False
Of course you can make up some reasoning that will result in that behavior. For example,
* the type ((,) a) must be Traversable * all Traversables should be Foldables * the "length" function should work on Foldables * `const 1` is a fine implementation of length .. etc.
(Those are by no means the only assumptions that would lead to the same results.)
But normally, when you have a set of assumptions that result in garbage, you don't just shrug and try to convince yourself that maybe the conclusions aren't so bad after all. The point of the type system is not to put stupid behavior on solid theoretical grounds; it's to reject incorrect programs, and "length (2,3)" is an incorrect program.
By analogy, ask the same question about, say, PHP.
Question: why is "foo" == TRUE in PHP? Answer: it makes perfect sense, once you understand blah blah herp derp.
No, it's stupid, and your reasoning is stupid if you can justify it.
_______________________________________________ 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.

On Wed, May 3, 2017 at 1:11 PM, Andrey Sverdlichenko
people who don't like absurd semantic
Absurd like topology? Like category theory? Heck, like negative numbers? -- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

Like the length of the entity which does not have a length. I absolutely
won't mind having this function under the name of foldDepth or
numberOfElements or maybe size, whatever, but the length is a linear
dimension, and even tree does not have it, leaving alone tuple. Naming in
software engineering is a hard problem, and here we failed miserably.
On Wed, May 3, 2017 at 1:37 PM Brandon Allbery
On Wed, May 3, 2017 at 1:11 PM, Andrey Sverdlichenko
wrote: people who don't like absurd semantic
Absurd like topology? Like category theory? Heck, like negative numbers?
-- brandon s allbery kf8nh sine nomine associates allbery.b@gmail.com ballbery@sinenomine.net unix, openafs, kerberos, infrastructure, xmonad http://sinenomine.net

On 2017-05-03 19:11, Andrey Sverdlichenko wrote:
This is probably twentieth time this question arises. Discussion quickly boils down to people liking convenient syntax sugar Foldable instance gives (traverse pair, etc), versus people who don't like absurd semantic which becomes correct with such instances.
Language like "absurd semantic" perpetuates the negativity/confrontation that Gershom was talking about. Please try to avoid such language. (It's absolutely fine to disagree, but phrasing matters.) Regards,

"Square root of negative one" doesn't make a lot of sense if you ignore the context of complex arithmetic. And it appears to make even less sense that this expression should have several different solutions. Yet quaternions are used today to describe the rotation of robots. In other words: Robots – more than meets the i! Robots are cool. Don't hate on robots. Don't be uncool. An analog is true for /Traversable/ and /Foldable/. Part of the missing context here is that you can write generic functions and later plug in things like the 1-tuple (/Identity/) and get cool things. Just look at lenses. What the instances in question really show is that some operations are transparent in relation to type-level products (i.e. tuples). A different place that shows the same are functions like "first" and "second" that you'll find in the context of profunctors, categories, and arrows. There's more than meets the eye here, and part of the reason you don't get to benefit a lot from it is that that's still an active area of research. From my own gut feeling it may well be where part of the future of programming lies. Which, in my eyes, is pretty cool. But then I'm just a random type still in the process of folding Haskell theory through my Identity. Cheers, MarLinn
participants (16)
-
amindfv@gmail.com
-
Andrey Sverdlichenko
-
Bardur Arantsson
-
Benno Fünfstück
-
Brandon Allbery
-
Chris Smith
-
Dmitry Olshansky
-
Gershom B
-
Jonathon Delgado
-
MarLinn
-
Michael Orlitzky
-
Nickolay Kudasov
-
Richard A. O'Keefe
-
Richard Eisenberg
-
Theodore Lief Gannon
-
Tony Morris