问题描述
我想知道为什么下面的作品(请注意Functor或applicative与示例无关)
trait Functor[F[_]]
trait applicative[F[_]] extends Functor[F]
但不是
trait Functor[F[_]]
trait applicative[F[_]] extends Functor[F[_]]
我的问题是 F vs F [_]
这里的规则是什么?
特别是编译器出现严重错误:
F [_]不接受任何类型参数,应为:
解决方法
下划线(_
)在定义站点(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
,
trait Functor[F[_]]
表示 Functor 需要类型构造器(带有孔的类型,当填充孔时会产生新的类型)。
然后,在这里trait Applicative[F[_]] extends Functor[F]
,您是说适用性也需要一个洞。因此,F
已经被理解为具有一个孔的东西,因此将其传递给 Functor 是有意义的。
最后,这里extends Functor[F[_]]
与extends Functor[F[T] forSome { type T } ]
相同,因此您正在填充F
中的空缺,因此它不再适用于 Functor 。
在Scala 3.2(Dotty)中存在一个plan,使F[_]
在定义站点和呼叫站点都表示same
在Scala 3.2中,_的含义从通配符更改为占位符 用于类型参数。
因此以下内容将成为有效的语法
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
为此,种类投影仪已将preemptively的类型lambda语法从F[?]
更改为F[*]
,以便为Scala 3存在类型释放?
。
作为旁注,请考虑当前如何在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提到的非正式表示法* => *
的语法。