2

使用简单类型的隐式值的便捷方法是什么?理想情况下,我想做这样的事情:

scala> :paste
// Entering paste mode (ctrl-D to finish)

type A = String
type B = String
implicit val a: A = "a"
implicit val b: B = "b" 
def c(implicit ab: A) = println(ab)

// Exiting paste mode, now interpreting.

defined type alias A
defined type alias B
a: A = a
b: B = b
c: (implicit ab: A)Unit

scala> c
<console>:13: error: ambiguous implicit values:
 both value a in object $iw of type => A
 and value b in object $iw of type => B
 match expected type A

也不能子类化最终案例类,如 String 或 Long

scala> class C extends String
<console>:11: error: illegal inheritance from final class String
       class C extends String
4

2 回答 2

3

虽然 Tim 是正确的,但他的方法会在字符串周围创建一个包装器,从而引入运行时开销。我们可以让编译器完成所有这些,而无需使用称为类型标记的技术创建新对象。以下代码无耻地取自无形源:

trait Tagged[U] 
type @@[+T, U] = T with Tagged[U]

class Tagger[U] {
  def apply[T](t : T) : T @@ U = t.asInstanceOf[T @@ U]
}

def tag[U] = new Tagger[U]

使用这些定义,您可以编写以下内容:

trait A
trait B

implicit def a: String @@ A = tag[A]("foo")
implicit def b: String @@ B = tag[B]("bar")

def foo(implicit a: String @@ A) = a.toString
def bar(implicit b: String @@ B) = b.toString

scala> foo
res21: String = foo

scala> bar
res22: String = bar
于 2013-07-12T06:53:22.060 回答
2

当您使用“类型”时,您定义的是类型的别名,而不是实际的新类型。

您要做的是定义一个实际的新类型。

case class A(a: String)
case class B(b: String)

implicit val a = A("a")
implicit val b = B("b")

def c(implicit ab: A) = println(ab.a)
于 2013-07-12T04:56:21.107 回答