Scala 为什么方法参数F可以与类型构造函数F同名?

Scala 为什么方法参数F可以与类型构造函数F同名?,scala,functional-programming,typeclass,Scala,Functional Programming,Typeclass,我在看约翰·德的“FP到最高点”视频。在代码中,他这样做是为了得到隐式对象: object Program { def apply[F[_]](implicit F: Program[F]): Program[F] = F } 这是否意味着变量名F(隐式F:Program[F]中的第一个)实际上是不同的F?这很令人困惑。他是否打算: object Program { def apply[F[_]](implicit ev: Program[F]): Program[

我在看约翰·德的“FP到最高点”视频。在代码中,他这样做是为了得到隐式对象:

  object Program {
    def apply[F[_]](implicit F: Program[F]): Program[F] = F
  }
这是否意味着变量名F(隐式F:Program[F]中的第一个)实际上是不同的
F
?这很令人困惑。他是否打算:

  object Program {
    def apply[F[_]](implicit ev: Program[F]): Program[F] = ev
  }

当返回
F
时,编译器如何知道他引用的是哪个
F
?类型构造函数还是范围中的变量

例如,功能参数
T
确实不同于类型参数
T

def f[T](T: T): T = T
f(42) // res0: Int = 42
编译器不会混淆,因为值存在于from类型中:

…存在两个独立的宇宙,类型宇宙和 价值的宇宙。在价值的宇宙中,我们有方法 将值作为圆括号中的参数(或偶尔卷曲) 大括号)。在类型的宇宙中,我们有类型构造函数,它接受类型 作为方括号中的参数

这个约定有时在处理类型类时使用。这意味着我们只想返回为
F
解析的typeclass实例。为了避免混淆,您可以使用您已经提出的
ev
方法,甚至

object Program {
  def apply[F[_]: Program]: Program[F] = implicitly[Program[F]]
}
作为旁注,在typeclass的伴生对象中使用
apply
方法的这个技巧允许我们避免隐式地使用
,例如,给定

trait Foo[T]
trait Bar[T]

trait Program[F[_]]
implicit val fooProgram: Program[Foo] = ???
implicit val barProgram: Program[Bar] = ???

object Program {
  def apply[F[_]: Program]: Program[F] = implicitly
}
然后我们就可以写了

Program[Bar]
而不是

implicitly[Program[Bar]]
当返回
F
时,编译器如何知道他引用的是哪个
F
?类型构造函数还是范围中的变量


编译器知道一个方法/函数只能返回一个值。因此,
=
后面的内容有一个类型,但不是一个类型。

顺便说一句,这不是Scala特有的。事实上,对于大多数语言以及所有主流语言来说,类型和值的世界是严格分开的。例如,它在Java中的工作原理完全相同。思考一下:
类t{t(t){returnt;}}