scala - Scala 中的 A[B[C]] 类型,即嵌套类型构造函数

标签 scala generics haskell

下面的代码可以编译

case class A(s:Int)
case class B(s:Int)
case class Box[T](t:T)

object DoublyNestedTypes extends App {
  println("hello")
  val l=List(Box(A(1)))
  val l2=Box(A(2))::l
  println(l2)
  val l3=Box(B(1))::l2
  println(l3)    
}

并产生:

hello
List(Box(A(2)), Box(A(1)))
List(Box(B(1)), Box(A(2)), Box(A(1)))

有人可以解释一下这里发生了什么吗? 为什么编译不会失败?还是运行时执行?

我原以为这会失败,因为 l 的类型是 List[Box[A]]Box(B(1)) 的类型是 Box[B],那么我如何在 前面添加 Box[B]列表[框[A]] ?

现在 l3 的类型是什么?

这是否与类型删除有关?

在 Haskell 中,等效代码会在编译时失败吗? (我的感觉是会的。)

最佳答案

当具有 A 类型的值 aB 类型元素的列表 l 时,a::l 不会失败,但会生成 List[C] 类型的列表,其中 C最小上限 类型 AB - 即它们最具体的通用父类(super class)型。如果类型 AB 完全不相关,您只会得到一个 List[Any]。这反射(reflect)在 :: 运算符的签名上(a::l 等同于 l.::(a)):

sealed abstract class List[+A] {
  def ::[B >: A] (x: B): List[B] = ...
}

你是对的,像这样的东西不会在 Haskell 中编译,那只是因为在 Haskell 中没有子类型这样的东西,所以最小上限的概念没有任何意义.

Scala这样做是好是坏,这是一个很有争议的问题。

关于scala - Scala 中的 A[B[C]] 类型,即嵌套类型构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22180610/

相关文章:

尽管总内存使用量只有 22Mb,但 Haskell 线程堆溢出?

haskell - haskell中有类型 'Any'吗?

compiler-construction - Scalas/Haskells 解析器组合器是否足够?

scala - Spark - 查找两个不同列中每个不同值的总出现次数

generics - Ada 通用程序

java - 如有必要,插入类型转换以保持类型安全

scala - 获取 Slick 中列的默认值?

scala - 如何拆分逗号分隔的字符串并在 Spark Scala 数据框中获取 n 个值?

c# - 从通用函数内部调用正确的重载

haskell - 翻转是否会改变函数的参数数据类型