# DeriveFoldable treatment of tuples is surprising

Anthony Clayden anthony_clayden at clear.net.nz
Sat Mar 25 03:08:36 UTC 2017

```> On Wed Mar 22 13:54:05 UTC 2017, Twan van Laarhoven wrote:

>> On 2017-03-21 21:34, David Feuer wrote:
>> This seems much too weird:
>>
>> *> :set -XDeriveFoldable
>> *> data Foo a = Foo ((a,a),a) deriving Foldable
>> *> length ((1,1),1)
>> 1
>> *> length \$ Foo ((1,1),1)
>> 3

Hmm.
*> length \$ Just ((1, 1), 1)
1
*> length \$ Just (1, 1)
1
*> length (1, 1)
1

> This is not unique to tuples, consider:

>      > :set -XDeriveFoldable
>      > data Foo a = Foo [[a]] deriving Foldable
>      > length [[1,2]]
>      1
>      > length \$ Foo [[1,2]]
>      2

> length \$ Just [[1, 2]]
1

Does the behaviour of other methods within Foldable
seem surprising for DeriveFoldable Foo a = Foo ((a, a), a)?

Did the FTP change touch DeriveFoldable?
(Silly question, yes it must have: `length` didn't used to
be in Foldable.)

> On Tue Mar 21 21:29:20 UTC 2017, Edward Kmett wrote:
> In general I think the current behavior is the least
surprising as it
> "walks all the a's it can" and is the only definition
compatible with
> further extension with Traversable. Right now there are no
instances
> provided by base that violate the "walk all the a's"
intuition

?? Are there instances in base
where the `a` appears more than once on RHS?

I can see only List and Array.
How would I have formed that "walk all the a's" intuition?
(For most of the Prelude instances,
`length`s result is hard-coded as 0 or 1.)

*> length (((1, 2), 3) :: Num a => ((a, a), a))
1
Doesn't seem to "walk all the a's" there.

I find pretty much all of these results surprising.
(Admittedly for different reasons in different cases.)

I think this is a good reason `length` should not be in
Foldable.
"lengthiness" just doesn't fit the abstraction.

AntC
```