如何在 Scala 中对更高种类的类型使用通配符?

发布于 2024-10-03 18:34:37 字数 325 浏览 4 评论 0原文

假设我有这个特征,

trait Ctx[C, V[_]]

我无法构造任何采用未指定第二个类型参数(通配符)的 Ctx 的方法签名。例如:

def test(c: Ctx[_, _]) = ()

无法编译(“错误:_$2 不接受类型参数,预期:一个”)。我也不能这样做

def test(c: Ctx[_, _[_]]) = ()

“错误:_$2 不接受类型参数”)。我缺少什么?

Let's say I have this trait

trait Ctx[C, V[_]]

I am unable to construct any method signature that takes a Ctx of which the second type parameter is unspecified (wildcard). E.g. this:

def test(c: Ctx[_, _]) = ()

doesn't compile ("error: _$2 takes no type parameters, expected: one"). Neither can I do

def test(c: Ctx[_, _[_]]) = ()

("error: _$2 does not take type parameters"). What am I missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

绿萝 2024-10-10 18:34:37

我能够定义这个:

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 是不同类型构造函数的对象(OptionList em> 在我的例子中)。我提供的第一个解决方案不允许您这样做。

编辑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) }

I'm able to define this one:

def test[V[X]](c:Ctx[_,V]) {}

And it seems to work ok with type inference:

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)

Edit: I suspect it won't be practical to replace Ctx to use an abstract type, but this is what I was able to do:

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

Using an abstract type for V spares you the complicated (or impossible) task of figuring the type parameter syntax for a wildcard type constructor. Additionally as demonstrated in the ListBuffer example you can then handle objects where the V is a different type constructor (Option and List in my example). The first solution I provided would not allow you to do that.

Edit 2: How about?

trait AbstractCtx[C] { type W[X] }
trait Ctx[C,V[_]] extends AbstractCtx[C] { type W[X] = V[X] }
def test(ctx:AbstractCtx[_]) { println(ctx) }
是你 2024-10-10 18:34:37

您需要为 Ctx 的第二个参数传递类型构造函数。如果您只传递 _,Scala 无法推断出正确的类型。也不可能使用通配符定义类型构造函数(即 _[_]] 。请注意,在第一个示例中,错误消息中的 _$2 指的是作为整体作为第二个参数传递给 Ctx 的类型,但在第二个示例中,_$2 指的是 _[_]

<console>:6: error: _$2 does not take type parameters
       def test( c: Ctx[ _, _[ _ ]]) {}
                            ^

以下内容有效,因为此处的 VCtx 所期望的正确类型的类型构造函数。

def test[V[_]]( c: Ctx[ _, V]) {}

You need to pass a type constructor for the second argument of Ctx. Scala is not able to infer the correct kind if you just pass _. Neither is it possible to define a type constructor with wildcards (i.e. _[_]] on the fly. Note that in your first example _$2 in the error message refers to the type passed as second argument to Ctx as a whole. In the second example however _$2 refers to the the first wildcard type in _[_]. See the location indicator in the error messages:

<console>:6: error: _$2 does not take type parameters
       def test( c: Ctx[ _, _[ _ ]]) {}
                            ^

The following works since here V is a type constructor of the right kind expected by Ctx.

def test[V[_]]( c: Ctx[ _, V]) {}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文