我正在观看John De Goes的“ FP to the Max”视频。在代码中,他做了这样的事情来获取隐式对象:
object Program {
def apply[F[_]](implicit F: Program[F]): Program[F] = F
}
这是否意味着变量名F(implicit F: Program[F]
中的第一个)实际上是一个不同的F
?这很令人困惑。他是否打算这样做:
object Program {
def apply[F[_]](implicit ev: Program[F]): Program[F] = ev
}
在返回F
时,编译器如何知道他指的是哪个F
?类型构造函数还是作用域中的变量?
答案 0 :(得分:4)
例如,函数参数T
与类型参数T
不同
def f[T](T: T): T = T
f(42) // res0: Int = 42
编译器不会感到困惑,因为来自类型的different universe中存在值:
...存在两个独立的宇宙,类型宇宙和 价值宇宙。在价值的宇宙中,我们有一些方法可以 将值作为圆括号中的参数(或偶尔卷曲) 大括号)。在类型的世界中,我们有类型构造函数,它接受类型 作为方括号中的参数。
在处理类型类时有时会使用此约定。这意味着我们只想返回解析为F
的typeclass实例。为避免混淆,您可以使用您已经提出的ev
方法,甚至
object Program {
def apply[F[_]: Program]: Program[F] = implicitly[Program[F]]
}
作为附带说明,在类型类的伴随对象中使用apply
方法的这种技巧使我们避免了必须使用implicitly
的情况,例如给定的
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]]
答案 1 :(得分:3)
在返回
F
时,编译器如何知道他指的是哪个F
?类型构造函数还是作用域中的变量?
编译器知道方法/函数只能返回一个值。因此,=
之后的类型是 ,而不是。