2013-07-12 96 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)