我有以下特质
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)
工作得很好。有什么区别?
答案 0 :(得分:2)
这实际上很有趣。似乎诀窍是类型参数。当你这样做
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将其转换为{{ 1}}并且一切都在那里工作。
我不确定是否有办法在不强制类型参数的情况下获取隐式行为,并且使用伪参数显然是不受欢迎的。但这似乎是你的代码和Scalaz之间的区别。