Surprisingly, This Works

Well, maybe not too surprising. Need -fglasgow-exts, obviously.

import Data.Typeable
import Data.Dynamic

class IShape a where
  width  :: a -> Int
  height :: a -> Int

data Shape = forall a. (Typeable a, IShape a) => Shape a

instance IShape Shape where
  width (Shape a) = width a
  height (Shape a) = height a

upcastShape :: (Typeable a, IShape a) => a -> Shape
upcastShape = Shape

downcastShape :: (Typeable a, IShape a) => Shape -> Maybe a
downcastShape (Shape a) = fromDynamic $ toDyn a
hoodwink.d enhanced