You can create a readLayer function that returns something like this:

    data OneLayer = forall a. Layer a => OneLayer a

Such that we get:

    -- Read next layer
    readLayer :: Handle -> IO OneLayer

Still, I feel that an ADT that combines all types is better as it fits the problem perfectly. Every time you add a new layer it will generate warnings for missing pattern matches.

Regards,
  Sumit