Re: DeriveFoldable treatment of tuples is surprising

2017-03-22 Thread Ryan Yates
Thanks for the clarification!

Ryan

On Wed, Mar 22, 2017 at 9:47 AM, Ryan Scott  wrote:

> I believe what Sven was saying is not that the Foldable instance for
> tuples are given "special treatment" (which is arguably an orthogonal
> discussion), but rather that -XDeriveFoldable special-cases tuples, which
> is certainly true.
>
> As Edward noted, there is one possible justification for this behavior
> w.r.t. things like newtype V3 a = V3 (a, a, a) deriving Foldable. But to be
> honest, I find this justification tenuous at best, given the confusion it
> causes when explaining how DeriveFunctor/DeriveFoldable/DeriveTraversable
> work to newcomers. Removing this special case would not only be simple, but
> it would also lead to a more consistent story overall.
>
> I would be curious to know how much code in the wild is actually taking
> advantage of a trick like newtype V3 a = V3 (a, a, a) deriving Foldable. If
> the breakage isn't terrible, then I propose we just rip off this wart.
>
> (This is basically a rehash of the thoughts I left at
> https://ghc.haskell.org/trac/ghc/ticket/13465#comment:3)
>
> Ryan S.
>
> ___
> ghc-devs mailing list
> ghc-devs@haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
>
>
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Re: DeriveFoldable treatment of tuples is surprising

2017-03-22 Thread Ryan Scott
I believe what Sven was saying is not that the Foldable instance for tuples
are given "special treatment" (which is arguably an orthogonal discussion),
but rather that -XDeriveFoldable special-cases tuples, which is certainly
true.

As Edward noted, there is one possible justification for this behavior
w.r.t. things like newtype V3 a = V3 (a, a, a) deriving Foldable. But to be
honest, I find this justification tenuous at best, given the confusion it
causes when explaining how DeriveFunctor/DeriveFoldable/DeriveTraversable
work to newcomers. Removing this special case would not only be simple, but
it would also lead to a more consistent story overall.

I would be curious to know how much code in the wild is actually taking
advantage of a trick like newtype V3 a = V3 (a, a, a) deriving Foldable. If
the breakage isn't terrible, then I propose we just rip off this wart.

(This is basically a rehash of the thoughts I left at
https://ghc.haskell.org/trac/ghc/ticket/13465#comment:3)

Ryan S.
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Re: DeriveFoldable treatment of tuples is surprising

2017-03-22 Thread Ryan Yates
On Wed, Mar 22, 2017 at 4:12 AM, Sven Panne  wrote:

> 2017-03-21 22:29 GMT+01:00 Edward Kmett :
>
>> [... 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. [...]
>>
>
> OTOH, the current behavior contradicts my intuition that wrapping a type
> into data/newtype plus using the deriving machinery is basically a no-op
> (modulo bottoms etc.). When I e.g. wrap a type t, I would be very surprised
> if the Eq/Ord instances of the wrapped type would behave differently than
> the one on t. I know that this is very handwavy argument, but I think the
> current behavior is *very* surprising.
>
> Somehow the current behavior seems to be incompatible with the FTP, where
> pairs are given a special treatment (if that't the right/intuitive choice
> is a completely different topic, though).
>

I'm not sure what you mean by "pairs are given a special treatment".
Tuples are given the only possible treatment:

data (,) a b = (a,b)

The b is the only place to fold over with a Foldable or change with a
Functor instance.  When things are monomorphic there are more options and
that leads to the least surprising, fold over all the options for:

data Pair a = Pair a a

or

data X a = X (a,a)

The (a,a) here is most certainly not the same thing as (a,b).  There is
something that is a bit surprising to me in that DerivingFoldable will not
a user declared data type for pair with two arguments:

> data Pair a = Pair a a deriving (Functor, Foldable, Show)
> data X a = X (Pair a) deriving (Functor, Foldable, Show)
> length (X (Pair 1 2))
2
> data Tup a b  = Tup a b deriving (Functor, Foldable, Show)
> data Y a = Y (Tup a a) deriving (Functor, Show)

:10:34: error:
• Can't make a derived instance of ‘Functor Y’:
Constructor ‘Y’ must use the type variable only as the last
argument of a data type
• In the data declaration for ‘Y’
> data Y a = Y (Tup a a) deriving (Foldable, Show)

:11:34: error:
• Can't make a derived instance of ‘Foldable Y’:
Constructor ‘Y’ must use the type variable only as the last
argument of a data type
• In the data declaration for ‘Y’
> data Y a = Y (Tup a a) deriving (Foldable, Show)

But it is happy to do just that with (a,a).


Ryan
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Re: DeriveFoldable treatment of tuples is surprising

2017-03-22 Thread Sven Panne
2017-03-21 22:29 GMT+01:00 Edward Kmett :

> [... 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. [...]
>

OTOH, the current behavior contradicts my intuition that wrapping a type
into data/newtype plus using the deriving machinery is basically a no-op
(modulo bottoms etc.). When I e.g. wrap a type t, I would be very surprised
if the Eq/Ord instances of the wrapped type would behave differently than
the one on t. I know that this is very handwavy argument, but I think the
current behavior is *very* surprising.

Somehow the current behavior seems to be incompatible with the FTP, where
pairs are given a special treatment (if that't the right/intuitive choice
is a completely different topic, though).

Given the fact that "deriving Foldable" is quite old and therefore hard to
change, I would at least suggest a big, fat warning in the documentation,
including various examples where intuition and implementation do not
necessarily meet.
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Re: DeriveFoldable treatment of tuples is surprising

2017-03-21 Thread Edward Kmett
As I recall, Richard Eisenberg has been pushing, off and on, for us to get
a better vocabulary to specify "how" something is derived, via
DeriveAnyClass, generalized newtype deriving, DeriveFoldable, etc.

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 and there is
a fair bit of user code for things like vector types that do things like

newtype V3 a = V3 (a,a,a,a)

replacing that with a data type isn't without cost because now converting
back and forth between that and a tuple could no longer be done for zero
cost with coercions. This style of code is more common among the
ML-turned-haskeller crowd, whom -- in my experience -- tend to think of it
as just giving the constructor paren around its arguments rather than as a
tuple.

Destroying Foldable for that and making working code not work just for
users to have to manually specify multiple tedious instances that should be
easily derivable shouldn't be a thing we do lightly. DeriveFunctor doesn't
consider that functors involved may be contravariant either. DeriveFoo
generally does something that is a best effort.

I'm more inclined to leave it on the list of things that DeriveFoo does
differently than GND, and as yet another argument pushing us to find a
better vocabulary for talking about deriving.

-Edward


On Tue, Mar 21, 2017 at 5:11 PM, David Feuer  wrote:

> The point is that there are two reasonable ways to do it, and the
> deriving mechanism, as a rule, does not make choices between
> reasonable alternatives.
>
> On Tue, Mar 21, 2017 at 5:05 PM, Jake McArthur 
> wrote:
> > I think it's a question of what one considers consistent. Is it more
> > consistent to treat tuples as transparent and consider every component
> with
> > type `a`, or is it more consistent to treat tuples as opaque and reuse
> the
> > existing Foldable instance for tuples even if it might cause a compile
> time
> > error?
> >
> >
> > On Tue, Mar 21, 2017, 4:34 PM 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
> >>
> >> I've opened Trac #13465 [*] for this. As I write there, I think the
> >> right thing is to refuse to derive Foldable for a type whose Foldable
> >> instance would currently fold over components of a tuple other than
> >> the last one.
> >>
> >> I could go either way on Traversable instances. One could argue that
> >> since all relevant components *must* be traversed, we should just go
> >> ahead and do that. Or one could argue that we should be consistent
> >> with Foldable and refuse to derive it.
> >>
> >> What do you all think?
> >>
> >> [*] https://ghc.haskell.org/trac/ghc/ticket/13465
> >> ___
> >> Glasgow-haskell-users mailing list
> >> glasgow-haskell-us...@haskell.org
> >> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
> ___
> Glasgow-haskell-users mailing list
> glasgow-haskell-us...@haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
>
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Re: DeriveFoldable treatment of tuples is surprising

2017-03-21 Thread Oleg Grenrus
For `Traversable` one have to `traverse` over everything:

traverse @Foo = forall f. Applicative f => (a -> f b) -> Foo a -> f
(Foo b)

~=  -> ((a,a), a) -> f ((b,b), b)

And thus the same behavior for `Foldable`.

You should define:

data Foo b a = Foo ((b,b), a) deriving Foldable

- Oleg

On 21.03.2017 23:11, David Feuer wrote:
> The point is that there are two reasonable ways to do it, and the
> deriving mechanism, as a rule, does not make choices between
> reasonable alternatives.
>
> On Tue, Mar 21, 2017 at 5:05 PM, Jake McArthur  
> wrote:
>> I think it's a question of what one considers consistent. Is it more
>> consistent to treat tuples as transparent and consider every component with
>> type `a`, or is it more consistent to treat tuples as opaque and reuse the
>> existing Foldable instance for tuples even if it might cause a compile time
>> error?
>>
>>
>> On Tue, Mar 21, 2017, 4:34 PM 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
>>>
>>> I've opened Trac #13465 [*] for this. As I write there, I think the
>>> right thing is to refuse to derive Foldable for a type whose Foldable
>>> instance would currently fold over components of a tuple other than
>>> the last one.
>>>
>>> I could go either way on Traversable instances. One could argue that
>>> since all relevant components *must* be traversed, we should just go
>>> ahead and do that. Or one could argue that we should be consistent
>>> with Foldable and refuse to derive it.
>>>
>>> What do you all think?
>>>
>>> [*] https://ghc.haskell.org/trac/ghc/ticket/13465
>>> ___
>>> Glasgow-haskell-users mailing list
>>> glasgow-haskell-us...@haskell.org
>>> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
> ___
> ghc-devs mailing list
> ghc-devs@haskell.org
> http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs




signature.asc
Description: OpenPGP digital signature
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


Re: DeriveFoldable treatment of tuples is surprising

2017-03-21 Thread David Feuer
The point is that there are two reasonable ways to do it, and the
deriving mechanism, as a rule, does not make choices between
reasonable alternatives.

On Tue, Mar 21, 2017 at 5:05 PM, Jake McArthur  wrote:
> I think it's a question of what one considers consistent. Is it more
> consistent to treat tuples as transparent and consider every component with
> type `a`, or is it more consistent to treat tuples as opaque and reuse the
> existing Foldable instance for tuples even if it might cause a compile time
> error?
>
>
> On Tue, Mar 21, 2017, 4:34 PM 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
>>
>> I've opened Trac #13465 [*] for this. As I write there, I think the
>> right thing is to refuse to derive Foldable for a type whose Foldable
>> instance would currently fold over components of a tuple other than
>> the last one.
>>
>> I could go either way on Traversable instances. One could argue that
>> since all relevant components *must* be traversed, we should just go
>> ahead and do that. Or one could argue that we should be consistent
>> with Foldable and refuse to derive it.
>>
>> What do you all think?
>>
>> [*] https://ghc.haskell.org/trac/ghc/ticket/13465
>> ___
>> Glasgow-haskell-users mailing list
>> glasgow-haskell-us...@haskell.org
>> http://mail.haskell.org/cgi-bin/mailman/listinfo/glasgow-haskell-users
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs


DeriveFoldable treatment of tuples is surprising

2017-03-21 Thread David Feuer
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

I've opened Trac #13465 [*] for this. As I write there, I think the
right thing is to refuse to derive Foldable for a type whose Foldable
instance would currently fold over components of a tuple other than
the last one.

I could go either way on Traversable instances. One could argue that
since all relevant components *must* be traversed, we should just go
ahead and do that. Or one could argue that we should be consistent
with Foldable and refuse to derive it.

What do you all think?

[*] https://ghc.haskell.org/trac/ghc/ticket/13465
___
ghc-devs mailing list
ghc-devs@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs