#4028 closed bug (wontfix)
Derived Data instance requires Data instances for unused type parameters
Reported by: | igloo | Owned by: | |
---|---|---|---|
Priority: | normal | Milestone: | Not GHC |
Component: | Compiler (Type checker) | Version: | 6.12.2 |
Keywords: | deriving | Cc: | alfonso.acosta@…, HoseinAttarzadeh, leather@…, dreixel |
Operating System: | Unknown/Multiple | Architecture: | Unknown/Multiple |
Type of failure: | None/Unknown | Test Case: | |
Blocked By: | Blocking: | ||
Related Tickets: | Differential Rev(s): | ||
Wiki Page: |
Description
First reported here: http://www.haskell.org/pipermail/glasgow-haskell-users/2010-April/018785.html
With this module:
{-# LANGUAGE DeriveDataTypeable #-} import Data.Data import Data.Typeable newtype FSVec s a = FSVec {unFSVec :: [a]} deriving (Eq, Typeable, Data)
6.12 now has a Data s
requirement on the Data (FSVec s a)
instance.
With 6.10.4:
*Main> :i FSVec newtype FSVec s a = FSVec {unFSVec :: [a]} -- Defined at q.hs:7:8-12 instance (Eq a) => Eq (FSVec s a) -- Defined at q.hs:8:14-15 instance (Data a, Typeable s) => Data (FSVec s a) -- Defined at q.hs:8:28-31 instance Typeable2 FSVec -- Defined at q.hs:8:18-25
With 6.12 (and the HEAD):
*Main> :i FSVec newtype FSVec s a = FSVec {unFSVec :: [a]} -- Defined at q.hs:7:8-12 instance (Eq a) => Eq (FSVec s a) -- Defined at q.hs:8:14-15 instance (Data s, Data a) => Data (FSVec s a) -- Defined at q.hs:8:28-31 instance Typeable2 FSVec -- Defined at q.hs:8:18-25
Change History (8)
comment:1 Changed 9 years ago by
Cc: | alfonso.acosta@… added |
---|
comment:2 Changed 9 years ago by
comment:3 Changed 9 years ago by
Cc: | HoseinAttarzadeh added |
---|
comment:4 Changed 9 years ago by
Cc: | leather@… dreixel added |
---|---|
Milestone: | 6.14.1 → Not GHC |
I've had a chance to look at this. Sadly, 6.10 is wrong here; the change was the fix to #3087. The derived instance looks like this, as you'll see if you do -ddump-deriv:
instance (Data s, Data a) => Data (FSVec s a) where dataCast2 f = Data.Typeable.gcast2 f -- <------- NOTA BENE dataTypeOf _ = tFSVec toConstr (FSVec _) = cFSVec gunfold k z _ = k (z FSVec) gfoldl k z (FSVec a1) = (z FSVec `k` a1) cFSVec = Data.Data.mkConstr tFSVec "FSVec" ["unFSVec"] Data.Data.Prefix tFSVec = Data.Data.mkDataType "T4028.FSVec" [cFSVec]
The new bit, compared to 6.10, is the definition of dataCast2
. It is defined in the Data class thus
class Data a where dataCast2 :: Typeable2 t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a)
and gcast2
has this type:
gcast2 :: forall t,t',a,b. (Typeable2 t, Typeable2 t') => c (t a b) -> Maybe (c (t' a b))
Now to typecheck the instance
instance (Data a, Data s) => Data (FSVec s a) where dataCast2 f = gcast2 f
we need that (Data a, Data s)
context. Try that exact instance declaration and you'll see. And there you are.
If you want to know about dataCast2
it's all in Section 7 of the SYB2 paper http://research.microsoft.com/en-us/um/people/simonpj/papers/hmap/gmap2.ps.
If you don't need dataCast2
you can define it to return Nothing
:
dataCast2 f = Nothing
but you can't use deriving
for that; you'd have to write out the derived instance yourself.
I'm not sure how to help you here. I can see that since 's' is phantom it seems odd to require (Data s)
but that's what the type checker will require. My brain has forgotten the details of dataCast2
and friends.
Maybe some generic programming experts (at Utrecht, for example) might help? I'm adding Sean Leather to the cc list.
I'll leave this open, but not because there is a bug as specified; rather maybe there is a better design of the Data library waiting to be discovered. I'll milestone it as 'Not GHC' though.
I suppose another design would be for derived 'Data' not to define dataCast1,2
, but #3087 specifically asked for them to be so!
Simon
comment:5 follow-up: 6 Changed 9 years ago by
Consider the following different choices of Data instances for FSVec:
newtype FSVec s a = FSVec {unFSVec :: [a]} deriving (Eq, Typeable) instance (Typeable s, Data a) => Data (FSVec s a) newtype FSVec1 s a = FSVec1 {unFSVec1 :: [a]} deriving (Eq, Typeable) instance (Typeable s, Data a) => Data (FSVec1 s a) where dataCast1 f = Data.Typeable.gcast1 f newtype FSVec2 s a = FSVec2 {unFSVec2 :: [a]} deriving (Eq, Typeable) instance (Data s, Data a) => Data (FSVec2 s a) where dataCast2 f = Data.Typeable.gcast2 f
Let's now test their behavior when extending a generic function with an adhoc case:
-- We need to define ext2Q, which uses dataCast2. -- ext1Q, which is defined in the library, uses dataCast1. newtype Q r a = Q { unQ :: a -> r } ext2Q :: (Data d, Typeable2 t) => (d -> q) -> (forall d1 d2. (Data d1, Data d2) => t d1 d2 -> q) -> d -> q ext2Q def ext arg = case dataCast2 (Q ext) of Just (Q ext') -> ext' arg Nothing -> def arg test, test1, test2 :: Char test = (const 'p') `ext2Q` (\(FSVec _) -> 'q') $ (FSVec "" :: FSVec () Char) test1 = (const 'p') `ext2Q` (\(FSVec1 _) -> 'q') $ (FSVec1 "" :: FSVec1 () Char) test2 = (const 'p') `ext2Q` (\(FSVec2 _) -> 'q') $ (FSVec2 "" :: FSVec2 () Char) main = print (test, test1, test2)
From my perspective, only test3 behaves correctly, and hence we should define dataCast2 for FSVec as ghc 6.12 does. Note also that FSVec is an instance of Typeable2, so it's only sensible to use dataCast2 for it.
comment:7 Changed 8 years ago by
Resolution: | → wontfix |
---|---|
Status: | new → closed |
dreixel says that he thinks nothing should be done, and no dissenters, so closing this ticket.
comment:8 Changed 2 years ago by
Keywords: | deriving added |
---|
This has an impact on packet paramterized-data and unfortunately as a consequence is a major blocker for upgrading the ForSyDe packet.