简体   繁体   English

`F[_ <: A] <: B` 在类型级别和 `f: A => B` 在值级别之间的类比

[英]Analogy between `F[_ <: A] <: B` at type-level and `f: A => B` at value-level

Assuming F[_ <: A] <: B as type-level analog of f: A => B , let [F[_ <: Int] <: List[Int], A <: Int] , then should't type application F[A] yield List[Int] when A = Int , so f(List(42)) should compile in the following case假设F[_ <: A] <: B作为f: A => B的类型级模拟,让[F[_ <: Int] <: List[Int], A <: Int] ,那么不应该type application F[A] yield List[Int] when A = Int ,所以f(List(42))应该在以下情况下编译

$ scala3-repl
scala> def f[F[_ <: Int] <: List[Int], A <: Int](as: F[A]) = as
def f[F[_$1] <: List[Int], A <: Int](as: F[A]): F[A]

scala> f(List(42))
1 |f(List(42))
  |  ^^^^^^^^
  |Found:    List[Int]
  |Required: F[A]
  |
  |where:    A is a type variable with constraint <: Int
  |          F is a type variable with constraint <: [_$1 <: Int] =>> List[Int]

Applying the error message by explicitly providing type parameters makes it work通过显式提供类型参数应用错误消息使其工作

scala> f[[_ <: Int] =>> List[Int], Int](List(42))
val res0: List[Int] = List(42)

Where does the analogy break?类比在哪里中断? Where is my mental model of considering F[_ <: Int] <: List[Int] as a type-level function from Int to List[Int] wrong?考虑F[_ <: Int] <: List[Int]作为从IntList[Int]的类型级别 function 的我的心理 model 错在哪里?

Firstly regarding inferring type lambdas, I think that type inference would not go to the extent of coming up with type lambdas just to satisfy the constraints otherwise intuitively it would seem like everything would essentially be able typecheck with some convoluted type lambda and that would not be useful in picking up type errors.首先,关于推断类型 lambdas,我认为类型推断不会 go 到提出类型 lambdas 只是为了满足约束的程度,否则直观上看起来一切都可以使用一些复杂的类型 lambda 进行类型检查,而这不会在拾取类型错误时很有用。

As to why f[List, Int](List(42)) fails to compile (and thus fails to get inferred) we would need to refer to the Subtyping Rules of type lambdas:至于为什么f[List, Int](List(42))无法编译(因此无法推断),我们需要参考 lambdas 类型的子类型规则

Assume two type lambdas假设有两种类型的 lambda

 type TL1 = [X >: L1 <: U1] =>> R1 type TL2 = [X >: L2 <: U2] =>> R2

Then TL1 <: TL2 , if那么TL1 <: TL2 ,如果

  • the type interval L2..U2 is contained in the type interval L1..U1 (ie L1 <: L2 and U2 <: U1 ),类型区间L2..U2包含在类型区间L1..U1 (即L1 <: L2U2 <: U1 ),
  • R1 <: R2

Also note that:另请注意:

A partially applied type constructor such as List is assumed to be equivalent to its eta expansion.部分应用的类型构造函数(例如List )被假定为等效于它的 eta 扩展。 Ie, List = [X] =>> List[X] .即, List = [X] =>> List[X] This allows type constructors to be compared with type lambdas.这允许将类型构造函数与类型 lambda 进行比较。

Which means all of these will compile:这意味着所有这些都将编译:

f[[_ <: Int] =>> List[Int], Int](List(42)) //author's compiler example
f[[_] =>> List[Int], Int](List(42)) //input type bounds can be wider, output stays the same
f[[_] =>> List[42], Int](List(42)) //input wider, output narrower
f[[x <: Int] =>> List[x], Int](List(42))//input same, output narrower

And all of these will not:所有这些都不会:

f[[x] =>> List[x], Int](List(42)) //input type bounds can be wider but in this case it will also make the output wider
f[List, Int](List(42)) //equivalent to preceding case
f[[_ <: 42] =>> List[Int], Int](List(42)) //input type bounds cannot be narrower

In the case of:如果是:

def f[F[x] <: List[x], A <: Int](as: F[A]) = as

If you view it from the same type lambda perspective f[[x] =>> List[x], Int](List(42)) should work, and thus f[List, Int](List(42)) would also compile (and be inferred).如果您从同一类型 lambda 角度查看它f[[x] =>> List[x], Int](List(42))应该可以工作,因此f[List, Int](List(42))也可以编译(并被推断)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM