我认为,我有两个问题。
我想有一套标记类型,图形的所有内容至少在图萨拉3.3.1中是<代码>Animal。 下面是我来的:
// In ReproDef.scala
object ReproDef {
type SubtypeTuple[T, L <: Tuple] <: Tuple = L match {
case EmptyTuple => EmptyTuple
case head *: tail => AsSubtype[T, head]#Out *: SubtypeTuple[T, tail]
}
class AsSubtype[T, U] {
type Out = U
}
given [T, U <: T]: AsSubtype[T, U] = new AsSubtype[T, U]
sealed trait Animal
case class Cat() extends Animal
case class Dog() extends Animal
case class Bird() extends Animal
val validTuple: SubtypeTuple[Cat | Dog | Bird, (Cat, Dog, Bird)] = Cat() *: Dog() *: Bird() *: EmptyTuple
val validTuple2: SubtypeTuple[Animal, (Animal, Animal)] = (Cat(), Dog())
val validTuple3: (Animal, Animal) = validTuple2
def toSeq[L <: Tuple](tup: SubtypeTuple[Animal, L]): Seq[Animal] = {
tup match {
case empty: EmptyTuple => Seq.empty
case (head: Animal) *: (tail: SubtypeTuple[Animal, tail_]) => head +: toSeq(tail)
}
}
}
(批量披露:我有不同的解决办法,但效果较差。) 以上法典是由ChatGPT产生的,但应当这样做。 我发现的错误至少是相同的。
Now here comes my first question: is there a better way to formulate this concept of a tuple where each element is at least a certain type T?
我的第二个问题是,我希望能够将只含有动物的les改成动物的 Se。 彩色类型包含一种<代码>toList方法,但有时只使用:
// In ReproUse.scala
def foo(): Unit = {
val sig: (ReproDef.Cat, ReproDef.Dog) = (ReproDef.Cat(), ReproDef.Dog())
def myId(x: Tuple): Tuple = x
val x: Seq[ReproDef.Animal] = myId(sig).toList // Compiler error, see below
println(myId(sig).toList) // Works, also without myId of course
}
相差错:
Found: List[Tuple.Union[(?1 : Tuple)]]
Required: Seq[testdyn.ReproDef.Animal]
where: ?1 is an unknown value of type Tuple
Note: a match type could not be fully reduced:
trying to reduce Tuple.Union[(?1 : Tuple)]
trying to reduce scala.Tuple.Fold[(?1 : Tuple), Nothing, [x, y] =>> x | y]
failed since selector (?1 : Tuple)
does not match case EmptyTuple => Nothing
and cannot be shown to be disjoint from it either.
Therefore, reduction cannot advance to the remaining case
case h *: t => h | scala.Tuple.Fold[t, Nothing, [x, y] =>> x | y] [7:35]
为了避免这种类型的错误,我也界定了我自己的基调,见第一部法典。 然而,这还造成一种类型的错误:
// In ReproUse.scala
def bar(): Unit = {
val sig: (ReproDef.Cat, ReproDef.Dog) = (ReproDef.Cat(), ReproDef.Dog())
println(ReproDef.toSeq(sig))
}
错误:
Found: (sig : (testdyn.ReproDef.Cat, testdyn.ReproDef.Dog))
Required: testdyn.ReproDef.SubtypeTuple[testdyn.ReproDef.Animal, L]
where: L is a type variable with constraint <: Tuple
Note: a match type could not be fully reduced:
trying to reduce testdyn.ReproDef.SubtypeTuple[testdyn.ReproDef.Animal, L]
failed since selector L
does not match case EmptyTuple => EmptyTuple
and cannot be shown to be disjoint from it either.
Therefore, reduction cannot advance to the remaining case
case head *: tail => testdyn.ReproDef.AsSubtype[testdyn.ReproDef.Animal, head]#Out *:
testdyn.ReproDef.SubtypeTuple[testdyn.ReproDef.Animal, tail] [14:28]
My custom toSeq
method does work in the file ReproDef.scala
, the problem starts occurring only when I want to use that method outside the file.
I think I am simply getting confused where the boundary is for typechecking, and I am probably expecting too much. Can someone explain to me my oversight, and what kind of type annotations I have to add to get these small examples to compile? Or is there maybe a better match type I can use that Scala 3 can work with better? The main motivaiton for this question is that I will probably use this toSeq method quite a few times, so I d like it to cause as few type annotations as possible.