较高幼儿园类型's的flatMap返回类型被解析为基Iterable,而不是更高级的kinded类型本身



我有以下代码:

case class Foo[+CC[A] <: Iterable[A]](foo: CC[Int])

def customReduce[CC1[A] <: Iterable[A], CC2[A] <: Iterable[A]](foos: CC1[Foo[CC2]]): Foo[CC1] =
Foo(foos.flatMap(_.foo))

println(customReduce(Seq(Foo(Seq(1)))))

Foo是一个接受任何集合类型的类型。当我执行customReduce时,调用foos.flatMap应该返回与foos相同的类型,即CC1[Foo[CC2]],但编译器将其解析为基Iterable并抱怨:

type mismatch;
found   : Iterable[Int]
required: CC1[Int]

为什么会发生这种情况,我该如何解决?


EDIT:在Iterable扩展IterableOps之后,CC类型似乎固定为Iterable。如何使上述代码正常工作?

在Scala 2.13中,您可以使用scala.collection.Factory

def customReduce[CC1[A] <: Iterable[A], CC2[A] <: Iterable[A]](foos: CC1[Foo[CC2]])(implicit 
factory: Factory[Int, CC1[Int]]
): Foo[CC1] = Foo(foos.flatMap(_.foo).to(factory))

println(customReduce(Seq(Foo(Seq(1))))) // Foo(List(1))

这是我自己找到的解决方案:

由于flatMap来自IterableOps,而Foo::foo需要Iterable,因此我需要将CC1声明为IterableOpsIterable:的复合类型

def customReduce[CC1[A] <: Iterable[A] with IterableOps[A, CC1, CC1[A]], CC2[A] <: Iterable[A]](foos: CC1[Foo[CC2]]): Foo[CC1] =
Foo(foos.flatMap(_.foo))

现在,由于返回原始CC 的IterableOps.flatMap签名,flatMap正确解析为CC1

相关内容

最新更新