Synthesize constructor for opaque types

I think there are many use cases that are hard to represent using the current type hierarchy, and changing it would be a very good opportunity to try and address as much of that as possible, while staying as compatible as possible with current code. It seems to me to be quite a big feat so it would probably be smart not to rush it.

That said, while having the full power of newtype in opaque types would be extremely useful, especially when it comes to IArray and similar use cases, they are already very useful despite the weaknesses.

For example, many of the use cases in Haskell export the constructor/destructor. This is used all the time to make it possible to safely define multiple given instances. A notable example of this is Monoid:
https://hackage.haskell.org/package/base-4.14.0.0/docs/Data-Monoid.html

This use case fits perfectly with opaque types, and isn’t at all diminished by morally dubious pattern matching:

I think the problem of code downcasting from Any breaking in the future could be solved quite cleanly:

  • Even with the addition of Top as a supertype of Any, opaque types with an upper bound that is a subtype of Any will still have the problems described above. One solution to this could be to already now disallow downcasts to opaque types. That way, opaque types can still be converted into the underlying type via Any, but not the other way around. Then when the opaque type is changed to have Top as it’s upper bound, it will no longer be possible to cast it to Any.
  • If in the future someone wants morally dubious type conversions to be possible, they can use Any as the upper bound explicitly.

Not allowing downcasting to an opaque type also fits quite nicely with the fact that usually if I define an

opaque type MySpecialBox <: Box = Box

I probably don’t want someone to downcast from any Box to MySpecialBox. If on the other hand I have:

opaque type Boxish <: AnyRef = Box

I really see no way to prevent someone from turning something Boxish into a Box. A Top type doesn’t help at all. The only way to prevent that would be by restricting typed patterns quite radically, which would be an interesting move, but probably a bit too extreme. Actually @odersky, do you have an idea of how hard it would be to require a TypeTest instance for all pattern matching?

TL;DR:

  • Opaques are great, they will be even better with Top
  • Considering adding any kind of sugar like case opaque type should wait until we have Top
  • Downcasting to opaque types should be illegal (unless using the-method-which-should-not-be-named)
  • Let users worry about the other direction until we have Top