Hack to seal a type at the package level

package foo

private[foo] sealed trait Seal
private[foo] given Seal with {}

trait SealedWithinFoo(using Seal)

It’s not perfect, as it only precludes the definition of concrete types outside of foo. Still, it seems to guarantee that any subtype of SealedWithinFoo defined outside of foo cannot be inhabited.

Let me know if this approach has any other flaws.

1 Like

It seems to work fine:

Welcome to Scala 3.3.1 (17.0.8.1, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                
scala> object foo:
     | 
     |   private[foo] sealed trait Seal
     |   private[foo] given Seal with {}
     | 
     |   trait SealedWithinFoo(using Seal)
     | 
// defined object foo
                                                                                
scala> object outside extends foo.SealedWithinFoo
-- [E172] Type Error: ----------------------------------------------------------
1 |object outside extends foo.SealedWithinFoo
  |                                          ^
  |No given instance of type foo.Seal was found for parameter x$1 of constructor SealedWithinFoo in trait SealedWithinFoo
1 error found

1 Like

You don’t really need private[foo] on Sealed as it is sealed and thus can’t be instantiated outside foo, but good to have it as it prevents Sealed from being seen.

You also lose all the other goodies of sealed like exhaustive pattern matching

3 Likes

As mentioned here, raw sealing can more simply be achieved thusly:

package foo

trait SealedWithinFoo private[foo]()
1 Like