有什么方法可以映射一个用更高类型参数化的类型的值集合吗?
Is there any way to map over a collection of values of a type parameterized with a higher type?
我阅读了有关带有参数化边界的类型定义如何在块内非法(或类似的东西)的现有问题,但这对我的问题没有帮助:
type Cons[X]
class Higher[C[X] <: Cons[X]]
type AnyHigher = Higher[C] forSome { type C[X] <: Cons[X] }
Seq[AnyHigher]().map { h => h }
编译器:
can't existentially abstract over parameterized type C
Seq[AnyHigher]().map { h => h }
输入集合的元素类型无关,问题只在于映射函数的return类型。有没有办法解决?我尝试了各种重构:使映射函数成为一种方法,通过使代码通用并使用 AnyHigher
参数化来作弊,编写我自己的递归,但没有任何帮助。
解决方法是
Seq[AnyHigher]().map(new (AnyHigher => AnyHigher) {
override def apply(h: AnyHigher): AnyHigher = h
})
"can't existentially abstract over parameterized type..."
另一种解决方法是使 C[X]
成为类型成员而不是类型参数
type Cons[X]
class Higher {
type C[X] <: Cons[X]
}
object Higher {
type Aux[C0[X0] <: Cons[X0]] = Higher { type C[X] = C0[X] }
}
type AnyHigher = Higher
Seq[AnyHigher]().map(h => h)
并使用 Higher.Aux[C]
代替 Higher[C]
并使用 Higher
代替 Higher[C] forSome { type C[X] <: Cons[X] }
。
http://dotty.epfl.ch/docs/reference/dropped-features/existential-types.html
Existential type is a dropped feature, which makes the following code
illegal.
def foo: List[Class[T]] forSome { type T }
The proposed solution is to introduce an enclosing type that carries a
dependent type:
trait Bar {
type T
val value: List[Class[T]]
}
def foo: Bar
为什么@Dmytro Mitin 的回答是正确的,因为它既是类型安全的,又提供了不需要更改类型的本地解决方案,有点啰嗦。所以,至少暂时,我选择了引入超类型和转换:
sealed trait AnyHigher {
def apply() :Higher[T] forSome { type T[O] <: Cons[O] } =
this.asInstanceOf[Higher[T] forSome { type T[O] <: Cons[O] }]
}
class Higher[T[O] <: Cons[O]] extends AnyHigher
Seq[AnyHigher]().map(t => t)
它很丑,但少了一点,而且在 Scala 3 之前是临时的,它具有涵盖任何类型的通配符类型。
我阅读了有关带有参数化边界的类型定义如何在块内非法(或类似的东西)的现有问题,但这对我的问题没有帮助:
type Cons[X]
class Higher[C[X] <: Cons[X]]
type AnyHigher = Higher[C] forSome { type C[X] <: Cons[X] }
Seq[AnyHigher]().map { h => h }
编译器:
can't existentially abstract over parameterized type C
Seq[AnyHigher]().map { h => h }
输入集合的元素类型无关,问题只在于映射函数的return类型。有没有办法解决?我尝试了各种重构:使映射函数成为一种方法,通过使代码通用并使用 AnyHigher
参数化来作弊,编写我自己的递归,但没有任何帮助。
解决方法是
Seq[AnyHigher]().map(new (AnyHigher => AnyHigher) {
override def apply(h: AnyHigher): AnyHigher = h
})
"can't existentially abstract over parameterized type..."
另一种解决方法是使 C[X]
成为类型成员而不是类型参数
type Cons[X]
class Higher {
type C[X] <: Cons[X]
}
object Higher {
type Aux[C0[X0] <: Cons[X0]] = Higher { type C[X] = C0[X] }
}
type AnyHigher = Higher
Seq[AnyHigher]().map(h => h)
并使用 Higher.Aux[C]
代替 Higher[C]
并使用 Higher
代替 Higher[C] forSome { type C[X] <: Cons[X] }
。
http://dotty.epfl.ch/docs/reference/dropped-features/existential-types.html
Existential type is a dropped feature, which makes the following code illegal.
def foo: List[Class[T]] forSome { type T }
The proposed solution is to introduce an enclosing type that carries a dependent type:
trait Bar { type T val value: List[Class[T]] } def foo: Bar
为什么@Dmytro Mitin 的回答是正确的,因为它既是类型安全的,又提供了不需要更改类型的本地解决方案,有点啰嗦。所以,至少暂时,我选择了引入超类型和转换:
sealed trait AnyHigher {
def apply() :Higher[T] forSome { type T[O] <: Cons[O] } =
this.asInstanceOf[Higher[T] forSome { type T[O] <: Cons[O] }]
}
class Higher[T[O] <: Cons[O]] extends AnyHigher
Seq[AnyHigher]().map(t => t)
它很丑,但少了一点,而且在 Scala 3 之前是临时的,它具有涵盖任何类型的通配符类型。