将 apply 替换为运算符
Replace apply with operator
我有以下特点
trait Tr{
def process(query: String)
}
object Tr{
@inline def apply(implicit l: Tr): Tr = l
}
我想导入一些具有隐式值的对象并像这样调用它:
implicit val qpe: Tr = (i: String) => ()
val q: String = //some query
Tr.process(q) //compile error
Tr.apply.process(q) //OK!
但在 ScalaZ 中我们有以下对象:
object Functor {
@inline def apply[F[_]](implicit F: Functor[F]): Functor[F] = F
//...
}
和通话
Functor[List].lift((_: Int) + 3)
工作正常。有什么区别?
这个其实挺有意思的。看来诀窍是类型参数。当你这样做时
Tr.process(...)
它在 Tr
对象中查找名为 process
的方法,但找不到。这是搜索停止的地方。但是,Functor
采用类型参数。现在,单例对象不能有类型参数,所以当你写 Functor[List]
时,Scala 推断你只是 必须 调用 apply
方法并开始寻找暗示。可以通过向 Tr
对象的 apply
.
添加虚拟类型参数来验证该理论
trait Tr[F] {
def process(query: String)
}
object Tr {
@inline def apply[F](implicit l: Tr[F]): Tr[F] = l
}
现在,当您尝试调用 Tr[Int].process(...)
时,您不可能单独引用对象 Tr
,因为它不能有类型参数,因此 Scala 将其转换为Tr.apply[Int].process(...)
然后一切正常。
我不确定是否有办法在不强制类型参数的情况下获得隐式行为,并且显然不希望使用虚拟参数。但这似乎是您的代码与 Scalaz 的代码之间的区别。
我有以下特点
trait Tr{
def process(query: String)
}
object Tr{
@inline def apply(implicit l: Tr): Tr = l
}
我想导入一些具有隐式值的对象并像这样调用它:
implicit val qpe: Tr = (i: String) => ()
val q: String = //some query
Tr.process(q) //compile error
Tr.apply.process(q) //OK!
但在 ScalaZ 中我们有以下对象:
object Functor {
@inline def apply[F[_]](implicit F: Functor[F]): Functor[F] = F
//...
}
和通话
Functor[List].lift((_: Int) + 3)
工作正常。有什么区别?
这个其实挺有意思的。看来诀窍是类型参数。当你这样做时
Tr.process(...)
它在 Tr
对象中查找名为 process
的方法,但找不到。这是搜索停止的地方。但是,Functor
采用类型参数。现在,单例对象不能有类型参数,所以当你写 Functor[List]
时,Scala 推断你只是 必须 调用 apply
方法并开始寻找暗示。可以通过向 Tr
对象的 apply
.
trait Tr[F] {
def process(query: String)
}
object Tr {
@inline def apply[F](implicit l: Tr[F]): Tr[F] = l
}
现在,当您尝试调用 Tr[Int].process(...)
时,您不可能单独引用对象 Tr
,因为它不能有类型参数,因此 Scala 将其转换为Tr.apply[Int].process(...)
然后一切正常。
我不确定是否有办法在不强制类型参数的情况下获得隐式行为,并且显然不希望使用虚拟参数。但这似乎是您的代码与 Scalaz 的代码之间的区别。