Inferring instance constraints with DeriveAnyClass
Simon Peyton Jones
simonpj at microsoft.com
Tue Jun 21 13:51:40 UTC 2016
| forward scenarios. If there is a simple and easy-to-specify way to
| infer the simple cases properly though, I am certainly not opposed to
| it.
I think there is a simple easy-to-specify way to infer /all/ cases!
Simon
| -----Original Message-----
| From: Andres Löh [mailto:andres.loeh at gmail.com]
| Sent: 21 June 2016 12:24
| To: Pedro Magalhães (dreixel at gmail.com) <dreixel at gmail.com>
| Cc: Simon Peyton Jones <simonpj at microsoft.com>; Ryan Scott
| <ryan.gl.scott at gmail.com>; GHC developers <ghc-devs at haskell.org>
| Subject: Re: Inferring instance constraints with DeriveAnyClass
|
| Sorry for the late reply.
|
| I think the reason I proposed to reuse the algorithm for Functor was
| that (A) as Pedro says, it was the class most closely resembling the
| classes we wanted to write at the time, and (B) I almost certainly was
| not at all aware that there is special magic in the code for
| contravariant arguments. In general, I'm not overly eager to try to be
| too clever in inferring the right instance constraints. I think
| standalone deriving should be used in anything but the most straight-
| forward scenarios. If there is a simple and easy-to-specify way to
| infer the simple cases properly though, I am certainly not opposed to
| it.
|
| Cheers,
| Andres
|
| On Sat, Jun 18, 2016 at 1:55 PM, José Pedro Magalhães
| <dreixel at gmail.com> wrote:
| >
| >
| > On Sat, Jun 18, 2016 at 12:51 PM, Simon Peyton Jones
| > <simonpj at microsoft.com>
| > wrote:
| >>
| >>
| >>
| >> But no need to look at the data type’s constructors, as
| >> deriving(Functor) does.
| >
| >
| > Yes, that's right.
| >
| > I believe we've used the "derive Functor" strategy for inferring
| > constraints simply because all generic functions (over Generic1)
| that
| > we had in mind at the time were Functor-like, so that was an
| > appropriate first solution. But I totally agree that it can be
| improved!
| >
| >
| > Best regards,
| > Pedro
| >
| >>
| >>
| >>
| >> Simon
| >>
| >>
| >>
| >> 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.
| >>
| >>
| >>
| >>
| >>
| >> Best regards,
| >>
| >> Pedro
| >>
| >>
| >>
| >> On Fri, Jun 17, 2016 at 12:43 PM, Simon Peyton Jones
| >> <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 [2], 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.
| >>
| >> Simon
| >> _______________________________________________
| >> ghc-devs mailing list
| >> ghc-devs at haskell.org
| >>
| https://na01.safelinks.protection.outlook.com/?url=http%3a%2f%2fmail.
| >> haskell.org%2fcgi-bin%2fmailman%2flistinfo%2fghc-
| devs&data=01%7c01%7c
| >>
| simonpj%40064d.mgd.microsoft.com%7c0087fcdf47ce4b70daa908d399c68207%7
| >>
| c72f988bf86f141af91ab2d7cd011db47%7c1&sdata=gmMJ4kcKnMS2HQghLI3HKBqHV
| >> FzBmk4FFJa%2bUY%2bBv7c%3d
| >>
| >>
| >
| >
More information about the ghc-devs
mailing list