使用结构类型隐含

时间:2013-07-12 03:55:11

标签: scala

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

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

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:2)

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

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

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)