2013-06-02 108 views
3

我有這樣的代碼爲什麼隱式轉換在這裏不起作用?

trait Outer1 { 
    type Inner1 
} 

trait Outer2 { 
    type Inner2 

    val ev: Outer1#Inner1 =:= Inner2 

    def f: Outer1#Inner1 
} 


object Main { 

// My Problem here 
// def test1(o2: Outer2): o2.Inner2 = 
// o2.f         // <- type mismatch 

    def test2(o2: Outer2): o2.Inner2 = 
    o2.ev.apply(o2.f) 
} 

是否有任何機會,使test1的工作?爲什麼Scala編譯器不能看到ev並隱式應用它?

回答

3

兩個問題:首先,你的證據參數不是隱式的,因此也不會隱式由編譯器發現:

trait Outer1 { 
    type Inner1 
} 

trait Outer2 { 
    type Inner2 

    implicit val ev: Outer1#Inner1 =:= Inner2 

    def f: Outer1#Inner1 
} 

問題二,值的一員是not part of the standard implicit lookup scope。所以,你需要導入:

object Main { 
    def test1(o2: Outer2): o2.Inner2 = { 
    import o2.ev // ! 
    o2.f 
    } 
} 

編輯:抽象類型儘管檢查,如果我沒有記錯的話,是沒有辦法,你可以真正兌現Outer2,因爲你是怎麼回事證明其成員Inner2等於Outer1#Inner1Inner1是抽象的?這就是爲什麼我要求具體的場景,因爲從這個抽象的佈局,我不知道你會得到任何地方。

據我所知,證據只對依賴類型有意義,例如,

trait Outer1 { 
    type Inner1 
    def bar: Inner1 
} 

trait Outer2 { 
    type Inner2 
    val outer1: Outer1 { type Inner1 = Inner2 } 

    def foo: Inner2 = outer1.bar 
} 
+0

那麼,第一個問題是我的錯,我同意。第二個讓我很難過:我沒有看到'ev'(像'test2')的顯式使用和'ev'的顯式導入(就像在你的答案中)之間的任何有價值的區別。我認爲這是一個隱含的查找機制的設計缺陷。 –

+1

解決的辦法是將你的implicits放置在編譯器尋找它們的地方,因此鏈接。通常這會是伴侶對象,但實際的解決方案很大程度上取決於你的用例是什麼樣的,從這個例子來說有點難以判斷。也許你以另一種方式制定問題 - 更抽象地說明你想要達到的目標,然後詢問如何達到目標。 –

+0

我只是想讓我的方法在'Outer2'裏面,它綁定返回'Inner2'對象來使用它自己的一些代碼,它真的返回Inner1。我不希望任何額外的資格/導入指向編譯器,指出有證據表明Inner1 =:= Inner2:我通過ev值表示這一事實。我想找出在哪裏放置'ev'以確保編譯器能夠在沒有額外幫助的情況下找到它。 –