Higher Kinded Type 参数中下划线的使用规则
Rules for underscore usage in Higher Kinded Type parameters
我想知道为什么下面的工作(注意 Functor 或 Applicative 与示例无关)
trait Functor[F[_]]
trait Applicative[F[_]] extends Functor[F]
但不是
trait Functor[F[_]]
trait Applicative[F[_]] extends Functor[F[_]]
我的问题是 F 与 F[_]
这里的规则是什么?
特别是编译器给出了一个严重的错误:
F[_] takes no type parameters, expected: one
trait Functor[F[_]]
表示Functor需要一个类型构造函数(一个有空洞的类型,当空洞被填充时产生新的类型).
那么,这里 trait Applicative[F[_]] extends Functor[F]
你是说 Applicative 也需要有一个孔的东西。因此,F
已经被理解为有一个洞的东西,因此将它传递给 Functor 是有意义的。
最后,这里的 extends Functor[F[_]]
与 extends Functor[F[T] forSome { type T } ]
相同,所以你正在填补 F
中的空缺,因此它不再适用于 Functor.
下划线 (_
) 在定义站点 (1) 和调用站点 (2) 具有不同的含义。
(1) 在定义站点下划线表示泛型(类型参数)是类型构造函数(* => *
)而不是正确的类型(*
)。
trait A[X] // X is a proper type, *
// ^^^ definition
trait B[X] extends A[X] // X is a proper type, *
// ^^^ definition, ^^^ call
trait A[F[_]] // F is a type constructor, * => *
// ^^^^ definition
trait B[F[_]] extends A[F] // F is a type constructor, * => *
// ^^^^ definition, ^^^ call
因为在定义站点上已经强调过 F
是一个类型构造函数,所以在调用站点它总是被称为 F
(不需要额外的 _
如果您指的是相同类型的构造函数 F
).
(2) 在调用点,对于类型构造函数(* => *
) F
,F[_]
表示存在类型。存在类型是适当的类型 (*
)。
trait A[X] // X is a proper type, *
// ^^^ definition
trait B[F[_]] // F is a type constructor, * => *
extends A[F[_]] // F[_] is an existential type, *
// ^^^^ definition, ^^^^ call
定义站点和调用站点都存在一个plan in Scala 3.2 (Dotty) to make F[_]
mean the same
In Scala 3.2, the meaning of _ changes from wildcard to placeholder
for type parameter.
因此以下将成为有效语法
trait Applicative[F[_]] extends Functor[F[_]] // Both F[_] represent type lambda [X] =>> F[X]
目的是将通配符(存在)类型 F[_]
替换为 F[?]
。这在 Dotty REPL
中已经可见
Starting dotty REPL...
scala> val l: List[_] = List(42)
val l: List[?] = List(42)
如果使用 source:3.1 -deprecation
编译,警告已经出现
dotc -source:3.1 -deprecation Main.scala
-- Deprecation Warning: Main.scala:2:14 ----------------------------------------
2 | val l: List[_] = List(42)
| ^
| `_` is deprecated for wildcard arguments of types: use `?` instead
1 warning found
为此,kind-projector 已 preemptively 将其类型 lambda 语法从 F[?]
更改为 F[*]
,以便为 Scala 3 existential 释放 ?
类型。
作为旁注,请考虑当前如何在 Dotty
中表达类型构造函数的 kind
Starting dotty REPL...
scala> trait Functor[F <: [X] =>> Any]
| trait Applicative[F <: [X] =>> Any] extends Functor[F]
// defined trait Functor
// defined trait Applicative
scala> trait Applicative[F <: [X] =>> Any] extends Functor[[X] =>> F[X]]
// defined trait Applicative
类型 [X] =>> Any
的语法类似于上面 Dmytro 提到的非正式符号 * => *
。
我想知道为什么下面的工作(注意 Functor 或 Applicative 与示例无关)
trait Functor[F[_]]
trait Applicative[F[_]] extends Functor[F]
但不是
trait Functor[F[_]]
trait Applicative[F[_]] extends Functor[F[_]]
我的问题是 F 与 F[_]
这里的规则是什么?
特别是编译器给出了一个严重的错误:
F[_] takes no type parameters, expected: one
trait Functor[F[_]]
表示Functor需要一个类型构造函数(一个有空洞的类型,当空洞被填充时产生新的类型).
那么,这里 trait Applicative[F[_]] extends Functor[F]
你是说 Applicative 也需要有一个孔的东西。因此,F
已经被理解为有一个洞的东西,因此将它传递给 Functor 是有意义的。
最后,这里的 extends Functor[F[_]]
与 extends Functor[F[T] forSome { type T } ]
相同,所以你正在填补 F
中的空缺,因此它不再适用于 Functor.
下划线 (_
) 在定义站点 (1) 和调用站点 (2) 具有不同的含义。
(1) 在定义站点下划线表示泛型(类型参数)是类型构造函数(* => *
)而不是正确的类型(*
)。
trait A[X] // X is a proper type, *
// ^^^ definition
trait B[X] extends A[X] // X is a proper type, *
// ^^^ definition, ^^^ call
trait A[F[_]] // F is a type constructor, * => *
// ^^^^ definition
trait B[F[_]] extends A[F] // F is a type constructor, * => *
// ^^^^ definition, ^^^ call
因为在定义站点上已经强调过 F
是一个类型构造函数,所以在调用站点它总是被称为 F
(不需要额外的 _
如果您指的是相同类型的构造函数 F
).
(2) 在调用点,对于类型构造函数(* => *
) F
,F[_]
表示存在类型。存在类型是适当的类型 (*
)。
trait A[X] // X is a proper type, *
// ^^^ definition
trait B[F[_]] // F is a type constructor, * => *
extends A[F[_]] // F[_] is an existential type, *
// ^^^^ definition, ^^^^ call
定义站点和调用站点都存在一个plan in Scala 3.2 (Dotty) to make F[_]
mean the same
In Scala 3.2, the meaning of _ changes from wildcard to placeholder for type parameter.
因此以下将成为有效语法
trait Applicative[F[_]] extends Functor[F[_]] // Both F[_] represent type lambda [X] =>> F[X]
目的是将通配符(存在)类型 F[_]
替换为 F[?]
。这在 Dotty REPL
Starting dotty REPL...
scala> val l: List[_] = List(42)
val l: List[?] = List(42)
如果使用 source:3.1 -deprecation
编译,警告已经出现
dotc -source:3.1 -deprecation Main.scala
-- Deprecation Warning: Main.scala:2:14 ----------------------------------------
2 | val l: List[_] = List(42)
| ^
| `_` is deprecated for wildcard arguments of types: use `?` instead
1 warning found
为此,kind-projector 已 preemptively 将其类型 lambda 语法从 F[?]
更改为 F[*]
,以便为 Scala 3 existential 释放 ?
类型。
作为旁注,请考虑当前如何在 Dotty
中表达类型构造函数的 kindStarting dotty REPL...
scala> trait Functor[F <: [X] =>> Any]
| trait Applicative[F <: [X] =>> Any] extends Functor[F]
// defined trait Functor
// defined trait Applicative
scala> trait Applicative[F <: [X] =>> Any] extends Functor[[X] =>> F[X]]
// defined trait Applicative
类型 [X] =>> Any
的语法类似于上面 Dmytro 提到的非正式符号 * => *
。