当前位置: 首页 > 知识库问答 >
问题:

为什么多态函数不能接受 Scala 中的通配符(存在)类型?

闽承望
2023-03-14

在下面的示例中,我想知道为什么funPoly不能接受存在量化的类型值outersFromInnersEx,即使funEx可以。

case class InnerCassClass[I, E, O](i: I, e: E, o: O)
case class OuterCaseClass[I, E, O](inner: InnerCassClass[I, E, O])


val inner1 = InnerCassClass(5, "foo", 3.3f)
val inner2 = InnerCassClass(4.4f, 6, "bar")


// Doesn't work as expected due to invariance of type paramemters I, E, O (but confirm)
// val outersFromInnersAny: List[OuterCaseClass[Any, Any, Any]] = List(inner1, inner2).map(OuterCaseClass.apply)

val outersFromInnersEx: List[OuterCaseClass[_, _, _]] = List(inner1, inner2).map(OuterCaseClass.apply)

def funPoly[I, E, O](occ: List[OuterCaseClass[I, E, O]]): Unit = ()
def funEx(occ: List[OuterCaseClass[_, _, _]]): Unit = ()


// This doesn't work, but why?
val u1 = funPoly(outersFromInnersEx)

val u2 = funEx(outersFromInnersEx)

请注意,我在Scala 3中对此进行了测试(在线尝试),但在很大程度上,Scala 2中的问题相同,尽管这个特定示例在Scala 2中还有其他问题。

共有2个答案

南宫建白
2023-03-14

它是关于类型差异的,您可以通过更改funPoly来使其工作

case class InnerCassClass[I, E, O](i: I, e: E, o: O)
case class OuterCaseClass[I, E, O](inner: InnerCassClass[I, E, O])

case class InnerCassClass[+I, +E, +O](i: I, e: E, o: O)
case class OuterCaseClass[+I, +E, +O](inner: InnerCassClass[I, E, O])
廖诚
2023-03-14

请注意,这两种类型非常不同:

def funPoly[I, E, O](occ: List[OuterCaseClass[I, E, O]]): Unit = ()
def funEx(occ: List[OuterCaseClass[_, _, _]]): Unit = ()

第一个能够处理< code>OuterCaseClass对象的统一列表,其中每个对象的类型参数都是相同的。第二个可以处理< code>OuterCaseClass对象的混合列表,其中每个对象的类型参数(可能)都不同。

使类型参数协变“修复”了这个问题,因为< code>List[OuterCaseClass[_,_,_]]相当于< code>List[OuterCaseClass[Any,Any,Any]],您可以简单地将< code>funPoly的类型参数实例化为< code>Any,Any,Any,使其接受< code>funEx可以接受的任何内容。

一般来说,您可以将存在限定类型传递给多态函数。例如,这应该可以工作:

case class ListAndFunction[A](list: List[A], function: A => Int)
val a: ListAndFunction [_] = ListAndFunction[String](List("a"), _.length)
def mapFunction[A](a: ListAndFunction [A]): List[Int] =
  a.list.map(a.function)
mapFunction(a)
 类似资料:
  • 但是在scala中我需要使用: scala版本是有意义的,因为注释需要一个字符串数组。但是为什么上面的工作在java中,它不应该给出编译时错误吗? 下面的类'ArrayChecker'(我编写了一个类来说明这一点)会导致java编译时错误:

  • 问题内容: 我知道Java的泛型类型有各种各样的违反直觉的属性。特别是我不理解的一个,希望有人可以向我解释。为类或接口指定类型参数时,可以对其进行绑定,以使其必须使用来实现多个接口。但是,如果要实例化实际对象,则此方法不再起作用。很好,但是无法编译。考虑以下完整代码段: 似乎应该明确定义的语义-我想通过允许两种类型(而不只是一种类型)的交集,不会损失类型安全性。我敢肯定有一个解释。有谁知道它是什么

  • 问题内容: 阅读@RequestMapping文档:http : //static.springsource.org/spring/docs/2.5.x/api/org/springframework/web/bind/annotation/RequestMapping.html 它接受String数组参数作为其路径映射。 所以这可以使用java: 但是在scala中,我需要使用: Scala版本

  • 需要您的帮助,我不明白为什么会出现以下错误,我不是专业的postgresql开发人员。。 正如你可以看到创建的函数,那么为什么函数不存在? 错误:函数logintry(未知,未知,带时区的时间戳,整数)不存在第1行:选择logintry('Jon.Jones88@gmail.com','_@kjhfdb987',...^HINT:没有函数匹配给定的名称和参数类型。您可能需要添加显式类型转换。SQL

  • 谁能告诉我为什么函数参数不能是?这是函数参数在上声明并在函数返回时被取消分配的原因吗?没有办法保留参数值?只是糊涂了。请澄清。 多谢了。