Search code examples
scalaimplicit-conversionimplicittype-alias

How can I use implicit conversions for two types that resolve to the same base type?


type JSON = String
type YAML = String

implicit def json2yaml(in:JSON):YAML = "some conversion"

val js:JSON = "some json"
val yml: YAML = js

The code above assigns "some json" to yml. The implicit conversion is not used. Is that because both YAML and JSON resolve to String? Is there a way to make encourage the code to pick up the conversion?


Solution

  • Note that relationship between type and its alias is that of equivalence

    If 𝑡 is defined by a type alias type 𝑡 = 𝑇, then 𝑡 is equivalent to 𝑇.

    which means 𝑡 and 𝑇 are interchangeable in all contexts. When we define alias

    type JSON = String
    

    then String is not a "base" type of JSON, instead it is JSON itself. Thus

    implicit def json2yaml(in: JSON): YAML = "some conversion"
    

    is equivalent to

    implicit def json2yaml(in: String): String = "some conversion"
    

    which is why implicit conversion does not happen.

    Instead of implicit conversion (which tends to be discouraged) consider extension method approach like so

    case class Json(v: String)
    case class Yaml(v: String)
    
    implicit class JsonToJaml(json: Json) {
      def asYaml: Yaml = Yaml("some conversion which uses ${json.v}")
    }
    
    val js: Json = Json("some json")
    val yml: Yaml = js.asYaml