2013-07-12 55 views
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 

人们不能继承像字符串或长任

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

+1教我'左右:paste' –

回答

3

虽然蒂姆是正确的,他的方法会产生串绕的包装,从而引入运行时开销。我们可以让编译器完成所有这些工作,而无需使用称为类型标记的技术创建新对象。下面的代码是无耻地从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 
+0

这是值得一提的有关悬而未决标签和copmiler之间的[问题](https://issues.scala-lang.org/browse/SI-5183) – 4lex1v

2

当您使用“类型”您定义的别名最终case类对于一种类型,而不是实际的新类型。

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

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)