Lib module Dynamic: bug in instances for tuples

Joost Visser Joost.Visser@cwi.nl
Mon, 06 May 2002 19:54:06 +0200


Hi,

The library module Dynamic provides instances of the Typeable class for
various datatypes, among which tuples of various lengths. These
instances are incorrect, as demonstrated by the following snippet:

  Dynamic> (typeOf (True,False)) == ((\(Dynamic t _) -> t) (toDyn
(True,False)))
  False

In other words, the type representation produced via the "typeOf" member
is not equal to the type representation produced via the function
"toDyn". This is wrong. As a result, casting back and forth to the type
Dynamic fails:

  Dynamic> fromDynamic (toDyn (True,False)) :: Maybe (Bool,Bool)
  Nothing

The error is caused by the nested definition of tup2Tc in the following
instance declaration:

  instance (Typeable a, Typeable b) => Typeable (a,b) where
    typeOf tu = mkAppTy tup2Tc [typeOf (fst tu), typeOf (snd tu)]
      where
        fst :: (a,b) -> a
        fst = undefined
        snd :: (a,b) -> b
        snd = undefined

        tup2Tc = mkTyCon ","

If tup2Tc is made top-level, the error vanishes. Likewise for longer
tuples.

The reason that TyCons must be defined top-level is that they are
shared, so they can be mapped onto Ints and compared efficiently. When
defined nested inside the instance declaration, this sharing apparently
fails.

Regards,
  Joost Visser

PS: I'm using hugs98-Dec2001.