Scala 3是一种非 predicate 语言,通常不可能将更高的类型分配给正常类型(有触发吉拉德悖论的风险),但在现实中,一些类型分配似乎可以绕过这一规则:
trait Vec[T] type VV1 = Vec // paradox! type VV2 = [T] =>> Vec[T] // no paradox?
最后两行有什么区别?为什么第二种可能?
798qvoo81#
第二行是可能的,因为语言作者决定类型别名可以包含类型构造函数以保持一致性。如果List是一个类型,尽管它不是一个正确的类型,那么如果我们想要保持一致,它可以是一个类型别名。如果函数可以被修饰、部分应用或传递,那么类型也可以。
List
trait Vec[T] type VV1 = Vec // not! a paradox, but shorthand for type VV1 = [T] =>> Vec[T]
第二行等于第三行:参数化类型定义
type T[X] = R
被认为是一个非参数化定义的简写,右边是一个lambda类型:
type T = [X] =>> R
一个部分应用的类型构造函数,如List,被假定为等价于它的eta扩展。即List = [X] =>> List[X]。这允许将类型构造函数与类型lambda进行比较。有关详细信息,请参见specification。
List = [X] =>> List[X]
n3ipq98p2#
找到原因:在Scala中,高阶类型不能与类型名的语法相关联,0-type和2-type都可以分配给类型名。它们只是在食用时的行为不同:
type VV2 = [T <: AnyVal] =>> Vec[T] // no paradox? type NN = List[VV2] // still paradox! // : Type argument VV2 does not have the same kind as its bound
关于第一个定义type VV = Vec,由于某些解析歧义,它可能被编译器禁止
type VV = Vec
2条答案
按热度按时间798qvoo81#
第二行是可能的,因为语言作者决定类型别名可以包含类型构造函数以保持一致性。如果
List
是一个类型,尽管它不是一个正确的类型,那么如果我们想要保持一致,它可以是一个类型别名。如果函数可以被修饰、部分应用或传递,那么类型也可以。第二行等于第三行:
参数化类型定义
被认为是一个非参数化定义的简写,右边是一个lambda类型:
一个部分应用的类型构造函数,如
List
,被假定为等价于它的eta扩展。即List = [X] =>> List[X]
。这允许将类型构造函数与类型lambda进行比较。有关详细信息,请参见specification。
n3ipq98p2#
找到原因:在Scala中,高阶类型不能与类型名的语法相关联,0-type和2-type都可以分配给类型名。它们只是在食用时的行为不同:
关于第一个定义
type VV = Vec
,由于某些解析歧义,它可能被编译器禁止