[GHC] #13465: Foldable deriving treatment of tuples is too surprising

GHC ghc-devs at haskell.org
Wed Mar 22 01:10:22 UTC 2017


#13465: Foldable deriving treatment of tuples is too surprising
-------------------------------------+-------------------------------------
        Reporter:  dfeuer            |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.4.1
       Component:  Compiler          |              Version:  8.1
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  Other             |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by RyanGlScott):

 * cc: twanvl (added)


Comment:

 Ick. This is an eccentricity of
 `DeriveFunctor`/`DeriveFoldable`/`DeriveTraversable` that I've never been
 keen on fixing, but since folks are complaining about it, I suppose it
 should at least be addressed.

 It's a somewhat obscure piece of GHC trivia that `DeriveFunctor` //et
 al.// special-cases two type constructors:

 1. `(->)`
 2. Tuples

 The `(->)` special case is somewhat justifiable, as it's quite common to
 define `Functor` instances where the type parameter occurs to the left of
 an arrow. The tuples special-casing is more confusing to me, as I'm not
 sure what practical purpose it serves. I've cc'd twanvl, the original
 author of these `deriving` extensions, in case he can share some insight
 on why he chose to implement it that way.

 I too think the Right Thing™ to do here is to change the behavior so that
 we just call `fmap`/`foldMap`/`traverse` on occurrences of tuple types,
 and reject things like `data Foo a = Foo (a, a) deriving (Functor,
 Foldable, Traversable)`. But there's one thorny corner case to watch out
 for: unboxed tuples. An even more obscure piece of GHC trivia is that you
 can do this:

 {{{#!hs
 data Foo a = Foo (# a, a #) deriving (Functor, Foldable)
 }}}

 This is only possible because of special-casing, as calling
 `fmap`/`foldMap` on an entire unboxed tuple is ill-kinded (unless we were
 to adopt [https://ghc.haskell.org/trac/ghc/ticket/12708 levity-polymorphic
 versions] of `Functor` and `Foldable`, I suppose). Moreover, it would feel
 weird to allow `data Foo a = Foo (# a, a #)` but not `data Foo a = Foo (a,
 a)`. I suppose we could tweak the special-casing so that we reject unboxed
 tuples where the type parameter occurs somewhere other than the last
 field, which would at least make its behavior consistent with that of
 boxed tuples.

 But the biggest roadblock by far is that this would (1) make fewer
 programs compile than before, and (2) change the behavior of existing
 programs. I think we should definitely get some kind of community
 consensus (i.e., a GHC proposal) before marching forth with this, although
 I have a funny feeling that discussing the behavior of `deriving Foldable`
 on tuple types is not going to go well...

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13465#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list