[GHC] #13065: Prohibit user-defined Generic and Generic1 instances
GHC
ghc-devs at haskell.org
Wed Jan 4 18:50:45 UTC 2017
#13065: Prohibit user-defined Generic and Generic1 instances
-------------------------------------+-------------------------------------
Reporter: dfeuer | Owner:
Type: feature request | Status: new
Priority: normal | Milestone: 8.4.1
Component: Compiler | Version: 8.0.1
Resolution: | Keywords: Generics
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: Other | Test Case:
Blocked By: | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: |
-------------------------------------+-------------------------------------
Comment (by RyanGlScott):
I'm not as experienced with `Data.Data` as I am with `GHC.Generics`, so
take my comments with a grain of salt. But the impression that I've
gathered after working with it a little bit is that `Data.Data` has
slightly different goals than `GHC.Generics`.
With the former (`Data`), you mostly care about generically walking over
data structures. That seems to explain why `Data.Data` gives you only a
bare-minimum amount of metadata for each datatype and constructor, as
they're only useful insofar as they serve as signposts when you're deep in
a datatype traversal. Moreover, the documentation in `Data.Data` mentions
the phrase "public representation" in several places. It seems acceptable
to lie a little in certain `Data` instances—e.g., in primitive datatypes
like `Int`, or abstract types like `Map`—in order to give programmers
//some// interface that they can walk over.
With the latter (`Generic`), there's an expectation that the
representation type provides a faithful view of the datatype's structure
and metadata. It occurs to me that we really don't state this expectation
anywhere in the documentation, but this is nonetheless the reasoning that
David Terei alluded to when he made the change to disallow hand-written
`Generic` instances in 578fbeca31dd3d755e24e910c3a7327f92bc4ee3. If we
allow users to hand-write their `Generic` instances, then I feel that we
are allowing them to shoot themselves in the foot.
Of course, the other thing that `Data` and `Generic` have in common is
that they facilitate the ability to reduce boilerplate code. But even if
you can't write `Generic` instances for your abstract types, you can still
use `GHC.Generics` to help reduce boilerplate: just use the `Generic`
instance for an isomorphic type. For instance, if you want to think of
`Data.Map` as a list of key-value pairs, then you have the power to do so:
{{{#!hs
module Main (main) where
import Data.Map
import Generics.Deriving.Eq
import GHC.Generics
eqMapKVList :: (GEq k, GEq v) => Map k v -> Map k v -> Bool
eqMapKVList x y = geq (toListRep x) (toListRep y)
where
toListRep :: Map k v -> Rep [(k, v)] ()
toListRep = from . toList
main :: IO ()
main = do
print $ eqMapKVList (fromList [('a', 'b')]) (fromList [('a', 'b')])
print $ eqMapKVList (fromList [('a', 'b')]) (fromList [('a', 'c')])
}}}
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/13065#comment:5>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list