2016-09-22 94 views
2

我寫了這個代碼斯卡拉Implicits編譯錯誤

case class Foo(x: Int) 
case class Bar(y: Int) 
object Foo { 
    implicit def toBar(f: Foo) : Bar = { Bar(f.x) } 
    implicit def toBarList(fl: List[Foo]) : List[Bar] = {fl.map{x: Bar => x}} 

的toBarList功能不編譯。

<console>:17: error: type mismatch; 
found : Bar => Bar 
required: Foo => ? 
     implicit def toBarList(fl : List[Foo]) : List[Bar] = { fl.map{x : Bar => x}} 

但是不應該將implicits系統踢在這裏嗎?這意味着編譯器應該檢測到函數期望一個Bar的錯誤,但我傳遞了一個Foo。現在已經有一個隱式函數將Foo轉換爲Bar,所以應該使用它,並且應該可以工作。

那爲什麼不編譯?

+0

在第一個片段,'{fl.map {X:酒吧=> B}}',也許你的意思'{fl.map {X: Bar => x}}'或'{fl.map {b:Bar => b}}'。 – dveim

回答

2

map是一個採用函數參數的普通方法,List[Foo]上的map需要函數Foo。您已經提供了Bar - 特別是Bar => Bar的功能 - 但有一個從FooBar的隱式轉換並不意味着您有一個從Bar => BarFoo => Bar(這是該方法需要的)。

如果你想要這個工作你要麼需要從Foo提供一個函數,然後應用轉換(顯式或隱式),或者你需要提供從Bar => Bar的隱式轉換到Foo => Bar(類似您試圖從List[Foo]List[Bar]提供的那個,但是轉換髮生在另一個方向上,因爲Function1在其第一個參數中是逆變的,而List是協變的)。

(這畢竟是一個非常糟糕的主意,雖然)。

+0

請原諒我的無知。但是當編譯器發現我提供了Foo => Bar但它需要Bar => Bar。爲什麼沒有找到一個隱含的,並自動地把Foo轉換成Bar轉換呢?因此編譯器應該將我的Foo => Bar轉換轉換爲Bar => Bar轉換,因爲我在範圍內有一個Foo => Bar轉換。 –

+0

@KnowsNotMuch原因的核心是函數只是一個特定類的實例(碰巧有一些特殊的語法)。在這方面沒有特殊的框架 - 如果你需要一個'Foo => Bar'並且有一個Bar => Bar','Foo'到''Bar'的轉換不會對你有所幫助(就像它贏了一樣如果你有一個'List [Foo]'並且需要一個'List [Bar]'),那麼它將無法幫助你。 –