Non-unary 由一元类型构造函数限定的类型构造函数

Non-unary type constructor bounded by unary type constructor

标题试图描述以下子类型

implicitly[Map[Int, String] <:< Iterable[(Int, String)]]

类型参数 A 在此处被推断为 (Int, String)

def foo[A](cc: Iterable[A]): A = cc.head
lazy val e: (Int, String) = foo(Map.empty[Int, String])

然而,尝试使用类型参数边界实现类似的效果,我能做的最好的就是像这样显式指定类型构造函数的元数

def foo[F[x,y] <: Iterable[(x,y)], A, B](cc: F[A, B]): (A, B) = cc.head
lazy val e: (Int, String) = foo(Map.empty[Int, String])

因为以下错误

def foo[F[x] <: Iterable[x], A](cc: F[A]) = cc.head
lazy val e: (Int, String) = foo(Map.empty[Int, String])
// type mismatch;
// [error]  found   : A
// [error]  required: (Int, String)
// [error]   lazy val e: (Int, String) = foo(Map.empty[Int, String])
// [error]                                  ^

因此使用 Iterable 作为上限似乎我们需要一个签名来处理一元类型构造函数 SeqSet,以及一个单独的签名来处理 2-arity 类型构造函数 Map

def foo[F[x] <: Iterable[x], A](cc: F[A]): A                  // When F is Seq or Set
def foo[F[x,y] <: Iterable[(x,y)], A, B](cc: F[A, B]): (A, B) // When F is Map

有没有一种方法可以使用适用于所有三种类型的边界来获得单个签名?换句话说,我们如何编写一个适用于所有 collections?

的扩展方法?

我认为这里的问题是F设置为Map,善意是错误的。你可能会说:我有一些类型 X,它扩展了 F[A],所以当我向上转换它时,我可以将它用作 F[A] - 这反过来我们想要Iterable[A] 的子类型。这样问的话,听起来很难。

这就是为什么我个人会留在:

@ def foo[A](x: Iterable[A]): A = x.head
defined function foo

@ foo(List(1 -> "test"))
res24: (Int, String) = (1, "test")

@ foo(Map(1 -> "test"))
res25: (Int, String) = (1, "test")

"Give me any x that is an instance of Iterable[A] for A".

如果一定要推导的话……我大概也会走这条路。我认为这种限制是 CanBuildFrom 以其工作方式工作的原因 - 很难为部分类型提供匹配,特别是在像 Map 这样的情况下,所以让我们一次提供整个类型作为参数,以限制数量需要推理。