Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tagged Type vs class extends AnyVal

To introduce more type safety, we can either use tagged type provided by shapeless or create a class which extends AnyVal. What are the differences and advantage/disadvantage to use one over the other?

Example:

trait CountryCodeTag
type CountryCode = String @@ CountryCodeTag

class CountryCode(code: String) extends AnyVal
like image 383
gyoho Avatar asked Oct 14 '17 18:10

gyoho


1 Answers

type CountryCode = String @@ CountryCodeTag

+ String @@ CountryCodeTag is a subtype of String, i.e. all methods from String can be used directly: countryCode.toUpperCase.

String @@ CountryCodeTag can be accidentally used where some String is expected, i.e. it's less type-safe.

− Creating new values is a little awkward: "a".asInstanceOf[String @@ CountryCodeTag] or val tagger = new Tagger[CountryCodeTag]; tagger("a").

− Dependence on Shapeless (although this can be done manually).

class CountryCode(code: String) extends AnyVal

+ It's more type-safe.

− Methods from String are available with some extra efforts:

class CountryCode(val code: String) extends AnyVal
new CountryCode(countryCode.code.toUpperCase)

or

class CountryCode(val code: String) extends AnyVal 
object CountryCode {
  def unapply(...) = ...
}
countryCode match { case CountryCode(code) => new CountryCode(code.toUpperCase) }

or

case class CountryCode(code: String) extends AnyVal
countryCode.copy(code = countryCode.code.toUpperCase)

+ Creating new values is a little more natural: new CountryCode("a").

+ No extra dependencies (it's plain Scala).

like image 89
Dmytro Mitin Avatar answered Oct 29 '22 15:10

Dmytro Mitin