Scala暗示并键入别名

时间:2017-11-17 14:11:03

标签: scala

假设我有以下代码:

object Potato extends App {

  type CoolString = String
  type AwesomeString = String

  def potato(string: String)(implicit coolString: CoolString, awesomeString: AwesomeString) = {
    s"$string is a string. Oh, but don't forget - $coolString and also $awesomeString"
  }

  implicit val ice : CoolString = "Really Cold Ice"
  implicit val awe : AwesomeString = "Awe inspiring object"

  potato("Stringerino")

}

此代码失败并出现问题

[error] ... ambiguous implicit values:
[error]  both value ice in object Potato of type => Potato.CoolString
[error]  and value awe in object Potato of type => Potato.AwesomeString
[error]  match expected type Potato.CoolString
[error]   potato("Stringerino")

这种使用是否不可能?

1 个答案:

答案 0 :(得分:4)

  

这种使用是否不可能?

不仅不可能,依靠这样一种方法来接受像String这样的一般类型是隐含的是危险的。考虑一下,范围内的任何String实例都将成为传递给方法的合格候选者!

类型别名就是一个类型别名,仅此而已。对于编译器,CoolStringAwesomeString仅为String

更好的方法是利用标记类型。例如,这是tagged type using shapeless

import shapeless.tag.@@

trait CoolString
trait AwesomeString

type ReallyCoolString = String @@ CoolString
type ReallyAwesomeString = String @@ AwesomeString

然后:

import shapeless.tag

def potato(string: String)(implicit coolString: ReallyCoolString, awesomeString: ReallyAwesomeString) = {
  s"$string is a string. Oh, but don't forget - $coolString and also $awesomeString"
}

def main(args: Array[String]): Unit = {
  implicit val ice = tag[CoolString][String]("Really Cold Ice")
  implicit val awe = tag[AwesomeString][String]("Awe inspiring object")

  println(potato("Stringerino"))
}

收率:

Stringerino is a string. 
Oh, but don't forget - Really Cold Ice and also Awe inspiring object