Opened 2 years ago

Closed 2 years ago

#10831 closed bug (fixed)

Document conditions on deriving Functor

Reported by: htebalaka Owned by: RyanGlScott
Priority: low Milestone: 8.0.1
Component: Compiler (Type checker) Version: 7.10.2
Keywords: Cc: RyanGlScott
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Documentation bug Test Case:
Blocked By: Blocking:
Related Tickets: Differential Rev(s): Phab:D1293
Wiki Page:

Description (last modified by thomie)

GHC can derive Functor for Okay, but rejects the equivalent Bad.

{-# LANGUAGE DeriveFunctor #-}                                                                                   
data Okay f g a b = Inl (f a b) | Inr (g a b) deriving (Functor)
newtype Bad f g a b = Bad (Either (f a b) (g a b)) deriving (Functor)
    Can't make a derived instance of ‘Functor (Bad f g a)’:
      Constructor ‘Bad’ must use the type variable only as the last argument of a data type
    In the data declaration for ‘Bad’

Change History (10)

comment:1 Changed 2 years ago by thomie

Component: CompilerCompiler (Type checker)
Description: modified (diff)
Operating System: MacOS XUnknown/Multiple

This comment (option c) in compiler/typecheck/TcDeriv.hs says this is to be expected:

 cond_functorOK :: Bool -> Bool -> Condition
 -- OK for Functor/Foldable/Traversable class
 -- Currently: (a) at least one argument
 --            (b) don't use argument contravariantly
 --            (c) don't use argument in the wrong place, e.g. data T a = T (X a a)
 --            (d) optionally: don't use function types
 --            (e) no "stupid context" on data type

comment:2 Changed 2 years ago by rwbarton

Summary: DeriveFunctor not capable of deriving when wrapping EitherDocument conditions on deriving Functor
Type of failure: GHC rejects valid programDocumentation bug

Right, this is expected behavior. The compiler doesn't "look inside" the definitions of other data types when deriving Functor, it relies on Functor instances for those types. But that is not enough to handle the occurrence of b inside the first argument to Either. One would need another class

class Functor1 f where
  fmap1 :: (a -> b) -> f a x -> f b x
instance Functor1 Either

I note that there is no documentation in the User's Guide about when deriving Functor will succeed. That at least should be fixed, so I'm repurposing this ticket. Feel free to also submit a feature request if you like.

comment:3 Changed 2 years ago by simonpj

Cc: RyanGlScott added

Ryan Scott made an implementation-oriented stab at documenting Functor, Foldable, Traversable here: Commentary/Compiler/DeriveFunctor. But I think we still lack a user-oriented specification, and such a thing would be tremendously welcome.

Simon

comment:4 in reply to:  3 ; Changed 2 years ago by RyanGlScott

Replying to simonpj:

But I think we still lack a user-oriented specification, and such a thing would be tremendously welcome.

What exactly would we want from a "user-oriented specification"? Do we want to see the compile-time error messages improved? Or do we want to see particular portions of the Commentary page and/or users' guide fleshed out?

I'll admit that I didn't do a thorough job of how to follow along with DeriveFunctor's many nuances as a newcomer to GHC in the Commentary page (I had the privilege of understanding it before I wrote it), so please point out specific parts that need work.

comment:5 in reply to:  4 Changed 2 years ago by rwbarton

Replying to RyanGlScott:

Replying to simonpj:

But I think we still lack a user-oriented specification, and such a thing would be tremendously welcome.

What exactly would we want from a "user-oriented specification"? Do we want to see the compile-time error messages improved? Or do we want to see particular portions of the Commentary page and/or users' guide fleshed out?

The user's guide should contain an explanation sufficient for a user to understand what types will and will not work with deriving Functor. Ideally this should contain examples of both sorts.

The wiki is intended for developer-facing documentation; users shouldn't have to consult the wiki to find out how to use a feature.

I think the errors (at least the error appearing in this ticket; I haven't looked at others if there are any) are fine, assuming that there is documentation added to the user's guide that explains in more detail what is wrong here.

comment:6 Changed 2 years ago by RyanGlScott

The user's guide should contain an explanation sufficient for a user to understand what types will and will not work with deriving Functor. Ideally this should contain examples of both sorts.

The wiki is intended for developer-facing documentation; users shouldn't have to consult the wiki to find out how to use a feature.

OK, that makes sense. I definitely got a bit lazy by the time I got to the users' guide and more-or-less copypasted what was in the wiki—I'll try to address this when I get a chance.

comment:7 Changed 2 years ago by RyanGlScott

Differential Rev(s): Phab:D1293
Owner: set to RyanGlScott

comment:8 Changed 2 years ago by Austin Seipp <austin@…>

In e5bfd70/ghc:

docs: overhaul Derive{Functor,Foldable,Traversable} notes

The previous users' guide documentation was too implementation-oriented. This
attempts to make it more accessible to those who aren't familiar with how
`-XDeriveFunctor` and friends work (and more importantly, what will not work
when using them).

Fixes #10831.

Reviewed By: austin

Differential Revision: https://phabricator.haskell.org/D1293

GHC Trac Issues: #10831

comment:9 Changed 2 years ago by thoughtpolice

Milestone: 8.0.1
Status: newmerge

comment:10 Changed 2 years ago by thoughtpolice

Resolution: fixed
Status: mergeclosed

Whoops. Thanks for the fix Ryan - closing this, not setting it to merge. :)

Note: See TracTickets for help on using tickets.