After further study I believe existentials are not (at least alone) enough to solve the problem.
They do allow a heterogeneous graph type to be defined and populated:
:set -XExistentialQuantification
import Data.Graph.Inductive
import Data.Maybe as Maybe
data ShowBox = forall s. Show s => SB s
instance Show ShowBox where show (SB x) = "SB: " ++ show x
type ExQuantGraph = Gr ShowBox String
let g = insNode (0, SB 1)
$ insNode (1, SB 'a')
$ empty :: ExQuantGraph
And once you've loaded those ShowBoxes, you can retrieve them:
getSB :: ExQuantGraph -> Node -> ShowBox
getSB g n = Maybe.fromJust $ lab g n
But you can't unwrap them. The following:
getInt :: ShowBox -> Int
getInt (SB i) = i
will not compile, because it cannot infer that i is an Int:
todo/existentials.hs:19:21:
Couldn't match expected type ‘Int’ with actual type ‘s’
‘s’ is a rigid type variable bound by
a pattern with constructor
SB :: forall s. Show s => s -> ShowBox,
in an equation for ‘getInt’
at todo/existentials.hs:19:13
Relevant bindings include
i :: s (bound at todo/existentials.hs:19:16)
In the expression: i
In an equation for ‘getInt’: getInt (SB i) = i
Failed, modules loaded: none.