【发布时间】:2020-09-18 01:07:48
【问题描述】:
标题试图描述以下子类型
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 作为上限,我们似乎需要一个签名来处理一元类型构造函数Seq 和Set,以及一个单独的签名来处理二元类型构造函数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
有没有一种方法可以使用适用于所有三个的类型边界来获得单个签名?换一种说法,我们如何编写一个适用于所有集合的扩展方法?
【问题讨论】:
-
这种类型推断最好通过广义类型约束而不是类型界限(如您所见)来处理,因为编译器试图很难推断出可以编译的东西,而有了约束,它有更多信息来验证你需要什么。无论如何,为所有集合提供扩展方法通常很难而且没有意义,但您可能想阅读this
-
@LuisMiguelMejíaSuárez 只需发布正确的链接,因为您评论中的链接已损坏docs.scala-lang.org/overviews/core/…。所以看来 typeclass 是解决方案。
标签: scala dictionary scala-collections type-bounds type-constructor