Why is Bag's Data instance "broken"?

José Pedro Magalhães jpm at cs.uu.nl
Thu Sep 20 13:22:30 CEST 2012


Right now I was just planning to fix the missing dataCast1 from Bag, and
the rest from
Data.Data (see http://hackage.haskell.org/trac/ghc/ticket/7256). I think
those are just
a bug, unrelated to the abstraction story, no?


Cheers,
Pedro

On Thu, Sep 20, 2012 at 12:19 PM, Edward Kmett <ekmett at gmail.com> wrote:

> Note: It was probably built with an eye towards how Data.Map and the like
> performed abstraction. However, This isn't necessary to protect the
> invariants of a bag.
>
> The constructors exposed via Data do not have to be the actual
> constructors of the data type. With this you can quotient out the portions
> of the structure you don't want the user to be able to inspect.
>
> See the libraries@ proposal that I put in 3-4 weeks ago (which will have
> just passed) to fix all the broken Data instances for containers by using
> virtual constructors such as 'fromList', (which incidentally led to Milan
> finding huge space and time improvements in fromList).
>
> Effectively allowing the user to use the 'listToBag' as a "constructor"
> loses no information violates no invariants, and prevents code written for
> uniplate, SYB, etc. from having to crash, panic or give up upon the sight
> of a mkNoRepType.
>
> My reaction for years to the sight of a mkNoRepType and undefined gunfold
> has been to hang my head. Now I just fix them.
>
> -Edward
>
> On Wed, Aug 29, 2012 at 7:11 AM, José Pedro Magalhães <jpm at cs.uu.nl>wrote:
>
>> Hi Philip,
>>
>> On Wed, Aug 29, 2012 at 12:01 PM, Philip Holzenspies <
>> pkfh at st-andrews.ac.uk> wrote:
>>
>>> Dear GHCers,
>>>
>>> I'm performing traversals over GHC-API results (HsSyn et al). For this
>>> purpose, I'm using SYB generics.
>>>
>>> I found that I couldn't use "ext1Q" for a function with type "Data x =>
>>> Bag x -> String", i.e. that this function was never applied. The source of
>>> Bag's instance of the Data class seems to explain why:
>>>
>>>
>>> instance Data a => Data (Bag a) where
>>>   gfoldl k z b = z listToBag `k` bagToList b -- traverse abstract type
>>> abstractly
>>>   toConstr _   = abstractConstr $ "Bag("++show (typeOf
>>> (undefined::a))++")"
>>>   gunfold _ _  = error "gunfold"
>>>   dataTypeOf _ = mkNoRepType "Bag"
>>>
>>>
>>> Is there a rationale to not allow gunfolds and to keep toConstr abstract?
>>
>>
>> As far as I understand, this is to keep `Bag` itself abstract, preventing
>> users from inspecting its internals.
>>
>>
>>> More to the point for my needs, is there a reason to not allow dataCast1
>>> casting of Bags?
>>>
>>
>> That is a separate issue; I believe this instance is just missing a
>> `dataCast1 = gcast1` line.
>> All datatypes of kind `* -> *` should have such a definition.
>>
>> (Having a look at Data.Data, I guess the same applies to `Ptr a` and
>> `ForeignPtr a`.
>> And `Array a b` seems to be missing the `dataCast2` method. I propose
>> fixing all of these.)
>>
>>
>> Cheers,
>> Pedro
>>
>>
>>>
>>> Regards,
>>> Philip
>>> _______________________________________________
>>> Glasgow-haskell-users mailing list
>>> Glasgow-haskell-users at haskell.org
>>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>>>
>>
>>
>> _______________________________________________
>> Glasgow-haskell-users mailing list
>> Glasgow-haskell-users at haskell.org
>> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/glasgow-haskell-users/attachments/20120920/492e2ae8/attachment.htm>


More information about the Glasgow-haskell-users mailing list