包含不同类型的协变泛型列表的类型是什么?
What is the type of a covariant generic list that contains different types?
我在 Scala 中使用泛型并创建了以下内容:
package playingaround.playground
object myList extends App {
abstract class MyList[+T] {
def head: T
def tail: MyList[T]
def isEmpty: Boolean
def add[C >: T](int: C): MyList[C]
def printElements: String
}
object Empty extends MyList[Nothing] {
override def head: Nothing = throw new NoSuchElementException
override def tail: Nothing = throw new NoSuchElementException
override def isEmpty: Boolean = true
override def add[C >: Nothing](int: C): MyList[C] = new Cons(int, Empty)
override def printElements: String = ""
}
class Cons[+T](h: T, t: MyList[T]) extends MyList[T] {
override def head: T = h
override def tail: MyList[T] = t
override def isEmpty: Boolean = false
override def add[C >: T](int: C): MyList[C] = new Cons(int, this)
override def printElements: String = if (t.isEmpty) "" + h else h + " " + t.printElements
}
// Define lists
val intList = new Cons(1, new Cons(2, new Cons(3, Empty)))
val strList = new Cons("a", new Cons("b", new Cons("c", Empty)))
val mixList = new Cons("a", new Cons(2, new Cons(0.5, Empty)))
// Print them
println(mixList.printElements) // a 2 0.5
}
令我困惑的是 "mixList" 的工作原理。 mixList 是什么类型?如果我要在 val 中明确定义它的类型,我必须将它定义为什么?
maxList
是 Cons[Any]
协方差基本上意味着 T
的类型匹配也适用于 MyList[T]
。换句话说,如果 T1
是 T2
的子类型,您可以在需要 MyList[T2]
的地方使用 MyList[T1]
。
所以在编译对
的调用时
Cons[+T](h: T, t: MyList[T])
编译器将使用与
相同的类型匹配
Cons[+T](h: T, t: T)
它将选择与 h
和 t
类型兼容的 T
。每次调用 Cons
都会重复此过程,以便生成的类型与所有 Cons
对象中所有 h
值的所有类型兼容。
在这种情况下,与 "a"
、2
和 0.5
兼容的唯一类型是 Any
,因为这是唯一与 [= 兼容的类型30=]、Int
和 Double
。
我要补充一点,你总是可以在 REPL 中看到某些东西的类型
scala> abstract class MyList[+T]
defined class MyList
scala> object Empty extends MyList[Nothing]
defined object Empty
scala> class Cons[+T](h: T, t: MyList[T]) extends MyList[T]
defined class Cons
scala> val mixList = new Cons("a", new Cons(2, new Cons(0.5, Empty)))
mixList: Cons[Any] = Cons@67d32a54
或者您可以使用以下函数查看类型
import scala.reflect.runtime.universe.{TypeTag, Type, typeOf}
def getType[A: TypeTag](a: A): Type = typeOf[A]
println(getType(mixList)) // Cons[Any]
顺便说一句,在 Dotty (Scala 3) 中,mixList
的推断类型也是 Cons[Any]
,但您可以使用 Cons[String | Int | Double]
或 MyList[String | Int | Double]
类型手动注释它。
我在 Scala 中使用泛型并创建了以下内容:
package playingaround.playground
object myList extends App {
abstract class MyList[+T] {
def head: T
def tail: MyList[T]
def isEmpty: Boolean
def add[C >: T](int: C): MyList[C]
def printElements: String
}
object Empty extends MyList[Nothing] {
override def head: Nothing = throw new NoSuchElementException
override def tail: Nothing = throw new NoSuchElementException
override def isEmpty: Boolean = true
override def add[C >: Nothing](int: C): MyList[C] = new Cons(int, Empty)
override def printElements: String = ""
}
class Cons[+T](h: T, t: MyList[T]) extends MyList[T] {
override def head: T = h
override def tail: MyList[T] = t
override def isEmpty: Boolean = false
override def add[C >: T](int: C): MyList[C] = new Cons(int, this)
override def printElements: String = if (t.isEmpty) "" + h else h + " " + t.printElements
}
// Define lists
val intList = new Cons(1, new Cons(2, new Cons(3, Empty)))
val strList = new Cons("a", new Cons("b", new Cons("c", Empty)))
val mixList = new Cons("a", new Cons(2, new Cons(0.5, Empty)))
// Print them
println(mixList.printElements) // a 2 0.5
}
令我困惑的是 "mixList" 的工作原理。 mixList 是什么类型?如果我要在 val 中明确定义它的类型,我必须将它定义为什么?
maxList
是 Cons[Any]
协方差基本上意味着 T
的类型匹配也适用于 MyList[T]
。换句话说,如果 T1
是 T2
的子类型,您可以在需要 MyList[T2]
的地方使用 MyList[T1]
。
所以在编译对
的调用时Cons[+T](h: T, t: MyList[T])
编译器将使用与
相同的类型匹配Cons[+T](h: T, t: T)
它将选择与 h
和 t
类型兼容的 T
。每次调用 Cons
都会重复此过程,以便生成的类型与所有 Cons
对象中所有 h
值的所有类型兼容。
在这种情况下,与 "a"
、2
和 0.5
兼容的唯一类型是 Any
,因为这是唯一与 [= 兼容的类型30=]、Int
和 Double
。
我要补充一点,你总是可以在 REPL 中看到某些东西的类型
scala> abstract class MyList[+T]
defined class MyList
scala> object Empty extends MyList[Nothing]
defined object Empty
scala> class Cons[+T](h: T, t: MyList[T]) extends MyList[T]
defined class Cons
scala> val mixList = new Cons("a", new Cons(2, new Cons(0.5, Empty)))
mixList: Cons[Any] = Cons@67d32a54
或者您可以使用以下函数查看类型
import scala.reflect.runtime.universe.{TypeTag, Type, typeOf}
def getType[A: TypeTag](a: A): Type = typeOf[A]
println(getType(mixList)) // Cons[Any]
顺便说一句,在 Dotty (Scala 3) 中,mixList
的推断类型也是 Cons[Any]
,但您可以使用 Cons[String | Int | Double]
或 MyList[String | Int | Double]
类型手动注释它。