Scala 泛型,这 4 个泛型版本中的哪一个特定于哪个特定问题

标签 scala generics higher-kinded-types

这四个版本都可以编译,但我很好奇我们应该更喜欢一个选项而不是另一个选项的上下文。

// 1
def f[N, S <: Seq[N]](s: S)
// 2
def f[N, S[N] <: Seq[N]](s: S[N])

使用1而不是2时它们非常相似

2 强加 SN 作为通用参数,与 1 相同,但是它们之间有什么区别两个?

然后我们有更多常规设置。

// 3
def f[N, S[X] <: Seq[X]](s: S[N])
// 3.a
def f[N, S[X] <: Seq[X]](s: S[N]): S[Int]

根据我的理解,3授权提取通用容器类型以便稍后重用,并获得类似3.a的内容。

但是未声明的 X 泛型参数的含义是什么,我想这是一种声明特殊内容的方法,但我不明白。

// 4
def f[N, S[X] <: Seq[_]](s: S[N])

除了我所知道的 Seq[_] 代表 Seq[Any] 以外,我不知道该对 4 说什么

最后,我只是想了解有关这些工具及其特殊性的更多信息,以便更正确地完成工作。

最佳答案

// 2
def f[N, S[N] <: Seq[N]](s: S[N])

这里的想法是第一个 N参数和N S[N] <: Seq[N]中提到是完全独立的参数。他们只是共用同一个名字。

N S[N]中提到仅在其绑定(bind)的 <: Seq[N] 范围内可见。 N用于参数定义(s: S[N])来自第一个 N因为这是唯一的N参数对于参数类型定义可见。所以而不是 NS[N] <: Seq[N]您可以使用任何字母,这不会以任何方式影响您的参数类型。

// 4
def f[N, S[X] <: Seq[_]](s: S[N])

这里你刚刚忽略了X参数。

编辑:正如@alexey-romanov 在评论中提到的那样。 S[X] <: Seq[X] 之间有区别和S[X] <: Seq[_]

下面是一个显示差异的示例:

def f1[N, S[X] <: Seq[X]](s: S[N]) = ""

def f2[N, S[X] <: Seq[_]](s: S[N]) = ""

type Foo[A] = Seq[Int]

val foo: Foo[String] = Seq(2,3)

//f1(foo) -- compilation error
f2(foo)

这里的问题是,由于类型构造函数是一种“类型上的函数”,我们可以定义这样的“函数”,接受一种类型作为参数,但返回由与类型构造函数中使用的参数无关的另一个参数参数化的类型。 (参见类型Foo)

通过foo val 为 f2很好,因为 X被推断为 String 和 Foo[String]Seq[Int] 的“子类型”(实际上它们是相等的) ,但是当我们通过foo时至f1 X仍然是String但是Foo[String]不是 Seq[String] 的“子类型” (因为 Foo[String]==Seq[Int] 不是 Seq[String] 的子类型)

// 1
def f[N, S <: Seq[N]](s: S)

你在这里说过N用于Seq[N]与第一个参数 N 相同。所以这是一样的N

关于Scala 泛型,这 4 个泛型版本中的哪一个特定于哪个特定问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53359958/

相关文章:

java - 用可序列化函数包装不可序列化类型

scala - WARN ScalaRowValueReader:字段 'client'由数组支持,但是关联的Spark Schema不能反射(reflect)这一点

arrays - 用 TArray<XXX> 替换 XXX 数组是否安全

haskell - Haskell 有善统一吗?

scala - 带或不带 '_' 的高级类型构造函数

scala - scala中的==符号如何发音?

java - 如何在 Eclipse 中打开 Java、Scala 和 JRuby 的单个项目?

scala - 使用抽象类型而不是参数类型的 F-Bound 多态性?

Silverlight 中的 .Net 框架版本 : no List<T>. 查找方法?

haskell - 参数多态性和更高种类的类型之间有什么区别?