[英]How to use a wildcard for a higher-kinded type in Scala?
比方說我有這個特點
trait Ctx[C, V[_]]
我無法構造任何采用Ctx的方法簽名,其中第二個類型參數未指定(通配符)。 例如:
def test(c: Ctx[_, _]) = ()
不編譯( "error: _$2 takes no type parameters, expected: one"
)。 我也不能這樣做
def test(c: Ctx[_, _[_]]) = ()
( "error: _$2 does not take type parameters"
)。 我錯過了什么?
我能夠定義這個:
def test[V[X]](c:Ctx[_,V]) {}
它似乎適用於類型推斷:
scala> trait Ctx[ C, V[ _ ]]
defined trait Ctx
scala> def test[V[X]](c:Ctx[_,V]) {}
test: [V[X]](c: Ctx[_, V])Unit
scala> class P extends Ctx[Int, List]
defined class P
scala> new P
res0: P = P@1f49969
scala> test(res0)
編輯 :我懷疑將Ctx
替換為使用抽象類型是不切實際的,但這是我能夠做到的:
trait Ctx[C] { type V[X] }
class CtxOption[C] extends Ctx[C] { type V[X] = Option[X] }
class CtxList[C] extends Ctx[C] { type V[X] = List[X] }
def test(ctx:Ctx[_]) { println(ctx) }
val ctxOptInt = new CtxOption[Int]
val ctxListStr = new CtxList[String]
test(ctxOptInt)
test(ctxListStr)
val list = collection.mutable.ListBuffer[Ctx[_]]()
list += ctxOptInt
list += ctxListStr
list
使用V的抽象類型可以避免為通配符類型構造函數確定類型參數語法的復雜(或不可能)任務。 此外,如ListBuffer示例中所示,您可以處理V
是不同類型構造函數的對象(在我的示例中為Option和List )。 我提供的第一個解決方案不允許你這樣做。
編輯2 :怎么樣?
trait AbstractCtx[C] { type W[X] }
trait Ctx[C,V[_]] extends AbstractCtx[C] { type W[X] = V[X] }
def test(ctx:AbstractCtx[_]) { println(ctx) }
您需要為Ctx
的第二個參數傳遞一個類型構造函數。 如果你只是傳遞_
Scala無法推斷出正確的類型。 也不可能動態定義帶有通配符的類型構造函數(即_[_]]
。請注意,在第一個示例中,錯誤消息中的_$2
指的是作為整體作為第二個參數傳遞給Ctx
的類型。但是第二個例子_$2
引用了_[_]
的第一個通配符類型。請參閱錯誤消息中的位置指示符:
<console>:6: error: _$2 does not take type parameters
def test( c: Ctx[ _, _[ _ ]]) {}
^
以下工作,因為這里V
是Ctx
期望的正確類型的類型構造函數。
def test[V[_]]( c: Ctx[ _, V]) {}
這一切都在這里解釋。 關注底部的“常見陷阱”部分。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.