
data A = A deriving Show data B = B deriving Show data C = C deriving Show
data Foo = forall a. Show a => MkFoo a (Int -> Bool)
instance Show Foo where show (MkFoo a f) = show a
I'd like to point out that the only operation we can do on the first argument of MkFoo is to show to it. This is all we can ever do: we have no idea of its type but we know we can show it and get a String. Why not to apply show to start with (it won't be evaluated until required anyway)? Therefore, the data type Foo above is in all respects equivalent to
data Foo = MkFoo String (Int -> Bool)
and no existentials are ever needed. The following article explains elimination of existentials in more detail, touching upon the original problem, of bringing different types into union. http://okmij.org/ftp/Computation/Existentials.html