替换适用于操作员

时间:2017-11-20 16:15:47

标签: scala implicit

我有以下特质

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)

工作得很好。有什么区别?

1 个答案:

答案 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之间的区别。