推斷類型考慮下面的代碼爲什麼Scala編譯器不會與抽象類型
trait A { type B }
case class C extends A { type B = String }
def f[V <: A](b: V#B => V) = b
這一個編譯
f[C](a => new C())
但爲什麼這一個不編譯?
f(a => new C())
推斷類型考慮下面的代碼爲什麼Scala編譯器不會與抽象類型
trait A { type B }
case class C extends A { type B = String }
def f[V <: A](b: V#B => V) = b
這一個編譯
f[C](a => new C())
但爲什麼這一個不編譯?
f(a => new C())
如果推斷出在一個參數列表中的類型,那麼約束在隨後PARAM名單的使用對。 (請參閱SO上的許多類似問題。)
但是,在參數列表中沒有發生類似情況。
這不起作用或者:
scala> def g[V <: A](b: V => V#B) = b
g: [V <: A](b: V => V#B)V => V#B
scala> g((c: C) => "")
<console>:11: error: type mismatch;
found : String("")
required: ?#B
的?
意味着它沒有固定的V
,即使它只是解決了V
。
對比度:
scala> def k[V <: A](v: V)(f: V#B => V) = 42
k: [V <: A](v: V)(f: V#B => V)Int
scala> k(new C)(_ => new C)
res5: Int = 42
當前的選項來使用是-Ytyper-debug
。有時候可以理解輸出。
對於你的例子f(_ => new C)
,你可以看到它立即在x$1
上失敗,即使人們希望它回溯並糾正自己。
| | | | |-- ((x$1) => new C()) : pt=?#B => ? BYVALmode-EXPRmode-POLYmode (site: value res0 in $iw)
<console>:11: error: missing parameter type
f(_ => new C)
^
| | | | | |-- new C() EXPRmode (site: value $anonfun in $iw)
| | | | | | |-- new C BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value $anonfun in $iw)
| | | | | | | |-- new C EXPRmode-POLYmode-QUALmode (silent: value $anonfun in $iw)
| | | | | | | | |-- C FUNmode-TYPEmode (silent: value $anonfun in $iw)
| | | | | | | | | \-> C
| | | | | | | | \-> C
| | | | | | | \->()C
| | | | | | \-> C
| | | | | \-> <error> => C
| | | | solving for (V: ?V)
| | | | \-> C#B => C
還有
http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#local-type-inference
我相信問題是,它是否含糊解釋你的對象爲C
類型或A
,因爲兩者都是上界由A
。我想你可以爭辯說編譯器應該知道後者並不完全合理,因爲B
在A
內是抽象的。但我能得到這個工作,參照B
在A
直接,而不是通過V
:
scala> trait A { type B }
defined trait A
scala> case class C() extends A { type B = String }
defined class C
scala> def f[V <: A](b: A#B => V) = b
f: [V <: A](b: A#B => V)A#B => V
scala> f(a => new C())
res0: A#B => C = <function1>
您解決移動問題:RES0( 「42」)不起作用。 – 2014-10-10 08:15:19
公平起見,你只問過爲什麼底線不能編譯。 – acjay 2014-10-10 12:32:52