Scala-模式匹配特征,具有;“自我类型”;as类型参数给出未选中的警告

Scala-模式匹配特征,具有;“自我类型”;as类型参数给出未选中的警告,scala,generics,immutability,traits,generic-programming,Scala,Generics,Immutability,Traits,Generic Programming,我试图定义“不可变的setter特性”,以及这些特性的通用函数 我有一个工作的实现,但是我对模式匹配中的“未检查”警告感到有点不安。我真的不确定我能做些什么 type Point = (Double, Double) trait Sizable[A] { this: A => def size: Point /* immutable object value setter, returns a new of the same object*/ def size(poin

我试图定义“不可变的setter特性”,以及这些特性的通用函数

我有一个工作的实现,但是我对模式匹配中的“未检查”警告感到有点不安。我真的不确定我能做些什么

type Point = (Double, Double)

trait Sizable[A] {
  this: A =>
  def size: Point

  /* immutable object value setter, returns a new of the same object*/
  def size(point: Point): A with Sizable[A]
}

def partitionToSizable[T](elements: List[T]): 
  (List[T], List[T with Sizable[T]]) =
    elements.foldLeft((List[T](), List[T with Sizable[T]]()))((p, c) =>
      c match {
        case a: T with Sizable[T] => (p._1, p._2 ++ List(a))
        case a => (p._1 ++ List(a), p._2)
      })
上面的代码演示了这个问题

我甚至不确定取消选中T有多大问题,因为列表中的所有元素都有一个T类型,模式匹配的重点不是确定它的类型是否为T,因为我们已经知道了

理论上,由于sizeable的封闭函数的签名,它总是具有T类型

如果没有其他解决方案,我至少希望抑制警告@未选中的批注似乎不会抑制警告

如果我用Sizable[T]将case a:T修改为case a:Sizable[\uux],它将不会编译,因为结果类型显然不会确认为T


ClassTags或TypeTags可能会解决警告问题,但我怀疑它们实际上不是必需的。(这可能会产生性能开销,并且类型标签不适用于Scala.js)

我认为只要
案例a:sizeable[t@unchecked]=>a.size((15,20))
就可以了。

我认为只要
案例a:sizeable[t@unchecked]=>a.size((15,20))
这里的主要问题是
partitionToSizable
。它使用一个
List[T]
然后尝试将它划分为一个
List[T]
和一个
List[T,其中[T]]
。您正在获取一个单一类型的列表,然后说一个类型
T
实际上是两个不同的类型
T
T与sizeable[T]
。这表明您的类型设计存在问题。我建议先解决这个问题

一种解决方案可能是认识到,应该将大小相当的事物和不大小的事物表示为两种不同的类型。然后您可以使用以下签名:

def partitionToSizable[T1, T2 <: Sizable[T2]](
  elements: List[Either[T1, T2]]): (List[T1], List[T2])

def partitionToSizable[T1,T2这里的主要问题是
partitionToSizable
。它取一个
List[T]
,然后尝试将它划分为一个
List[T]
和一个
List[T]大小相当的[T]]
。您正在获取一个单一类型的列表,然后说一个类型
T
实际上是两个不同的类型
T
,而
T具有相当大的[T]
。这表明您的类型设计存在问题。我建议首先解决这个问题

一种解决方案可能是认识到,可大小的事物和不可大小的事物应表示为两种不同的类型。然后,您可以使用以下签名:

def partitionToSizable[T1, T2 <: Sizable[T2]](
  elements: List[Either[T1, T2]]): (List[T1], List[T2])


def partitionToSizable[T1,T2为什么需要如此复杂的Sizeable定义?它类似于我的单链表定义。@AntonDanilov你是什么意思?它不是一个列表,它提供了一个通用接口,可以创建一个新的不可变实例,只需更改一个属性。此外,它与Sizeable无关,这只是这个概念的一个示例。如果你知道更好的方法吗,我想以此作为答案。你知道case类复制吗?它比我认为的
Sizeable
更通用、更强大。@Simon我知道复制,它在一个例子中使用。问题是复制不是一个通用的概念,它只在具体的环境中可用案例类。如示例所示,Sizeable不是一个封闭的特性,因此它的实现数量未知,因此我无法在模式匹配中解析最终的类。即使我可以,那也会是很多样板文件。@Simon如果你知道更好的解决方案,我很高兴听到这一点。我无法想象案例类副本如何成为她的替代方案e、 为什么需要如此复杂的Sizeable定义?它类似于我的单链表定义。@AntonDanilov你是什么意思?它不是一个列表,它提供了一个通用的接口,可以创建一个新的不可变实例,只需一次属性更改。此外,它与Sizeable无关,这只是一个概念的示例。如果你知道有更好的方法可以做到这一点,我想以此作为答案。你知道case类copy吗?它比我认为的
Sizeable
更通用、更强大。@Simon我知道copy,它在一个例子中使用。问题是copy不是一个通用的概念,它只在具体的case c中可用lass。如示例所示,SIZEABLE不是一个封闭的特性,因此它的实现数量未知,因此我无法在模式匹配中解析最终类。即使我可以,那也会是很多样板文件。@Simon如果你知道更好的解决方案,我很高兴听到这一点。我无法想象case类副本在这里会是一个什么样的替代方案。这就是它本身并不能解决这个问题,因为我需要将这个块的结果转换为T,所以它就像
a.size((15,20)).asInstanceOf[T]
。我希望避免使用INSTANCEOF。此外,它也不能回答更紧迫的问题,是否有更好的解决方案,或者如果它确实是一个问题,那么它是未经检查的。您为什么需要强制转换?
sizeable[T]。size(Point)
返回
T
。我并不反对您的观点,Scala编译器会
错误:(125,20)类型不匹配;发现:可定位[T],材料大小[T@unchecked]必填项:T
你是对的,我省略了部分代码,这就是它在这里工作的原因。我用引起问题的部分更新了问题的示例。在这种情况下,Yawar的回答是正确的:这个分区没有意义。除非你还有一些扩展了
sizeable[T]的
T
子类型
还有一些没有呢?这本身并不能解决问题,因为我需要将这个块的结果转换为t,所以它就像
a.size((15,20)).asInstanceOf[t]
。我希望避免使用asInsta