为什么在这种更高种类的类型上调用 collect 时类型信息会丢失?
Why is the type information lost when calling collect on this higher-kinded type?
我试图熟悉 Scala 中的高级类型,因此我尝试实现这个简单的方法,该方法采用 Option
的可遍历并将其展平,就像通常展平它一样。但是,编译器会引发错误,因为函数 return 的类型是 Traversable[Any]
而不是 T[S]
。为什么会这样,我怎样才能让它正常工作?
def flatten[S, T[_] <: Traversable[_]](list: T[Option[S]]): T[S] = {
list.collect({ case Some(s) => s })
}
我想也许我错误地定义了 T
的类型,但我也尝试了 T[_]: Traversable
和 T[X] <: Traversable[X]
但它们也没有用。
当然,这行得通:
def flatten[S](list: Traversable[Option[S]]): Traversable[S] = {
list.collect({ case Some(s) => s })
}
但我不想丢失 return 类型的输入类型信息(调用 flatten(List[Option[T]])
应该 return List[T]
.
这是因为 collect
没有 return 一个 T
,它 return 只有一个 Traversable
。特征 Traversable
不知道 class 继承它的任何类型。
另外,你的 higher-kinded 类型是错误的,它应该是 T[x] <: Traversable[x]
以避免存在主义的怪异。你可以这样做:
def flatten[S, T[x] <: Traversable[x]](list: T[Option[S]])(
implicit ev: collection.generic.CanBuildFrom[Traversable[Option[S]], S, T[S]]
): T[S] = list.collect { case Some(s) => s }
,或者您最好听从 Luis Miguel Mejía Suárez 关于使用 typeclasses 的建议。如果可能,我还建议使用 Scala 2.13。
trait Flatten[F[_]] {
def flatten[S](list: F[Option[S]]): F[S]
}
object Flatten {
def flatten[S, F[_]](list: List[Option[S]])(implicit f: Flatten[F]) = f.flatten(list)
implicit val flattenList = new Flatten[List] {
def flatten[S](list: List[Option[S]]) = list.collect { case Some(s) => s }
}
}
我试图熟悉 Scala 中的高级类型,因此我尝试实现这个简单的方法,该方法采用 Option
的可遍历并将其展平,就像通常展平它一样。但是,编译器会引发错误,因为函数 return 的类型是 Traversable[Any]
而不是 T[S]
。为什么会这样,我怎样才能让它正常工作?
def flatten[S, T[_] <: Traversable[_]](list: T[Option[S]]): T[S] = {
list.collect({ case Some(s) => s })
}
我想也许我错误地定义了 T
的类型,但我也尝试了 T[_]: Traversable
和 T[X] <: Traversable[X]
但它们也没有用。
当然,这行得通:
def flatten[S](list: Traversable[Option[S]]): Traversable[S] = {
list.collect({ case Some(s) => s })
}
但我不想丢失 return 类型的输入类型信息(调用 flatten(List[Option[T]])
应该 return List[T]
.
这是因为 collect
没有 return 一个 T
,它 return 只有一个 Traversable
。特征 Traversable
不知道 class 继承它的任何类型。
另外,你的 higher-kinded 类型是错误的,它应该是 T[x] <: Traversable[x]
以避免存在主义的怪异。你可以这样做:
def flatten[S, T[x] <: Traversable[x]](list: T[Option[S]])(
implicit ev: collection.generic.CanBuildFrom[Traversable[Option[S]], S, T[S]]
): T[S] = list.collect { case Some(s) => s }
,或者您最好听从 Luis Miguel Mejía Suárez 关于使用 typeclasses 的建议。如果可能,我还建议使用 Scala 2.13。
trait Flatten[F[_]] {
def flatten[S](list: F[Option[S]]): F[S]
}
object Flatten {
def flatten[S, F[_]](list: List[Option[S]])(implicit f: Flatten[F]) = f.flatten(list)
implicit val flattenList = new Flatten[List] {
def flatten[S](list: List[Option[S]]) = list.collect { case Some(s) => s }
}
}