Scala 由一元类型构造函数限定的非一元类型构造函数
标题试图描述以下子类型Scala 由一元类型构造函数限定的非一元类型构造函数,scala,dictionary,scala-collections,type-bounds,type-constructor,Scala,Dictionary,Scala Collections,Type Bounds,Type Constructor,标题试图描述以下子类型 implicitly[Map[Int, String] <:< Iterable[(Int, String)]] 然而,为了使用类型参数边界实现类似的效果,我所能做的最好的事情就是像这样显式地指定类型构造函数的arity 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
implicitly[Map[Int, String] <:< Iterable[(Int, String)]]
然而,为了使用类型参数边界实现类似的效果,我所能做的最好的事情就是像这样显式地指定类型构造函数的arity
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])
有没有一种方法可以让一个签名使用适用于所有三种类型的类型边界?换一种说法,比如说,我们怎么能编写一个适用于所有集合的扩展方法呢?我认为这里的问题是
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")
“给我任何x
,它是Iterable[A]
的A
实例。”
如果我必须做一些推导。。。我可能也会走这条路。我认为这个限制就是
CanBuildFrom
工作方式的原因-为部分类型提供匹配很难,特别是在Map这样的情况下,所以让我们一次提供一个完整的类型作为参数,限制所需的推理次数。这种类型的推理最好由广义类型约束而不是类型边界(如您所示)来处理,因为编译器会尽力推断编译的内容,而通过约束,它有更多的信息来验证您所需的内容。无论如何,为所有集合提供扩展方法通常是相当困难的,毫无意义,但您可能希望阅读@LuisMiguelMejíaSuárez,因为您的评论中的链接已断开。因此,似乎typeclass就是解决方案。我不确定这是否回答了您的问题,所以请告诉我这是否需要改进
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] ^
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
@ 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")