Why is Bag's Data instance "broken"?

Edward Kmett ekmett at gmail.com
Thu Sep 20 13:19:22 CEST 2012

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.


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/8b38e830/attachment.htm>

More information about the Glasgow-haskell-users mailing list