But now we're talking block compilation. I think Zippel's two types are less significant than they appear. Certainly we want to distinguish different types of numbers at top level. We have a choice of representation. The only difference is in the organization of the tag namespace.
Opacity is an orthogonal issue.
I wouldn't use inheritance too much, since it inherits both type and implementation. And what's worse, it builds subtype implementations from supertype implementations. A generic function accepts arguments of several types. A polymorphic function can be specialized on any of several types.