Skip to content

quasi-Opaque types in Scala 2 #593

Open
@halotukozak

Description

In default Scala 2, we have a way to alias types. This is great as a way to make code more readable, but if your type logically has a more limited range of support then the type won't enforce this. Or if the type you are working with is used in different places to mean different things, then implicits wont know what to pick.

Opaque type aliases from Scala 3 provide type abstraction without any overhead. In Scala 2, a similar result could be achieved with value classes, but it has limitations and enforces "boxed" syntax, e.g.:

final case class ID(value: String) extends AnyVal

Seq[ID](...).forEach{ id=>
  println("Sth sth" + id.value)
}

Seq[String](ID("asdsadas").value)

My proposition allows to define quasi-opaque type without runtime overhead and with full IDE support.

object ID extends Opaque.Default[String]

  Seq[String](ID("DASDAS"))
  /*
  type mismatch;
    found   : CastableTest.this.ID.Type
    (which expands to)  com.avsystem.commons.opaque.Opaque.Hidden[String,CastableTest.this.ID.Tag]
    required: String
   */
  Seq[ID.Type]("DASDAS")
  /*
  type mismatch;
     found   : String("DASDAS")
     required: CastableTest.this.ID.Type
        (which expands to)  com.avsystem.commons.opaque.Opaque.Hidden[String,CastableTest.this.ID.Tag]
  Seq[ID.Type]("DASDAS")
   */

Seq[ID](...).forEach{ id=>
  println("Sth sth" + id)
}

object ID2 extends Subopaque.Default[String]

Seq[String](ID2("DASDAS")) //ok

Opaque is equivalent to

opaque type T = Original

SubOpaque is equivalent to:

opaque type T <: Original = Original

in Scala 3

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions