首页 > 解决方案 > Scala Generics,这 4 个通用版本中的哪个特定于哪个特定问题

问题描述

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

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

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

2强加S具有N与通用参数一样的通用参数,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])

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

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

标签: scalagenericshigher-kinded-types

解决方案


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

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

Nin 中提到的S[N]仅在其 bound 的范围内可见<: Seq[N]N参数定义中使用的参数(s: S[N])来自 first N,因为这是N参数类型定义中唯一可见的参数。因此,您可以使用任何字母代替Nin S[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],但是当我们传递foof1X仍然是一个StringFoo[String]不是的“子类型” Seq[String](因为 Foo[String]==Seq[ Int] 不是 Seq[String] 的子类型)

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

在这里你说Nused inSeq[N]与第一个参数相同N。所以这是一样的N


推荐阅读