高阶类型参数中下划线用法的规则

问题描述

我想知道为什么下面的作品(请注意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)在呼叫站点,对于类型构造函数(* => *FF[_]表示存在类型。存在类型是适当的类型(*)。

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提到的非正式表示法* => *的语法。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...