Inferring instance constraints with DeriveAnyClass
Simon Peyton Jones
simonpj at microsoft.com
Sat Jun 18 11:51:25 UTC 2016
Yes, but none of that has anything to do with a walk over the data type, as deriving(Functor) does!
You are right that what we need is the result of simplifying the instantiated constraint
(Generic [a], GC (Rep [a]))
Simplify that constraint (simplifyDeriv does that), including reducing type-function applications, and that’s your context.
But no need to look at the data type’s constructors, as deriving(Functor) does.
From: josepedromagalhaes at gmail.com [mailto:josepedromagalhaes at gmail.com] On Behalf Of José Pedro Magalhães
Sent: 18 June 2016 09:16
To: Simon Peyton Jones <simonpj at microsoft.com>
Cc: Ryan Scott <ryan.gl.scott at gmail.com>; Andres Löh <andres.loeh at gmail.com>; GHC developers <ghc-devs at haskell.org>
Subject: Re: Inferring instance constraints with DeriveAnyClass
I still don't think you can do it just from the default method's type. A typical case is the following:
class C a where
op :: a -> Int
default op :: (Generic a, GC (Rep a)) => a -> Int
When giving an instance C [a], you might well find out that you need C a =>, but this is not something
you can see in the type of the default method; it follows only after the expansion of Rep [a] and resolving
the GC constraint a number of times.
On Fri, Jun 17, 2016 at 12:43 PM, Simon Peyton Jones <simonpj at microsoft.com<mailto:simonpj at microsoft.com>> wrote:
| My question is then: why does DeriveAnyClass take the bizarre approach
| of co-opting the DeriveFunctor algorithm? Andres, you originally
| proposed this in #7346 , but I don't quite understand why you
| wanted to do it this way. Couldn't we infer the context simply from
| the contexts of the default method type signatures?
That last suggestion makes perfect sense to me. After all, we are going to generate an instance looking like
instance .. => C (T a) where
op1 = <default-op1>
op2 = <default-op2>
so all we need in ".." is enough context to satisfy the needs of <default-op1> etc.
Well, you need to take account of the class op type sig too:
class C a where
op :: Eq a => a -> a
default op :: (Eq a, Show a) => a -> a
We effectively define
default_op :: (Eq a, Show a) => a -> a
Now with DeriveAnyClass for lists, we effectively get
instance ... => C [a] where
op = default_op
What is ..? Well, we need (Eq [a], Show [a]); but we are given Eq [a] (because that's op's instantiated type. So Show a is all we need in the end.
ghc-devs mailing list
ghc-devs at haskell.org<mailto:ghc-devs at haskell.org>
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the ghc-devs