Scala Kittens:隐式 Sequencer 值似乎不适用于上下文绑定语法



根据我的理解,以下两个函数及其调用应该是相同的:

def f1[L1 <: HList, L2](xs: L1)(implicit sequencer: Sequencer.Aux[L1, Option, L2]) {
println(xs.sequence)
}
def f2[L1 <: HList : Sequencer.Aux[*, Option, L2], L2](xs: L1) {
println(xs.sequence)
}
f1[Option[Int] :: Option[String] :: HNil, Int :: String :: HNil](Some(42) :: Some("foo") :: HNil)
f2[Option[Int] :: Option[String] :: HNil, Int :: String :: HNil](Some(42) :: Some("foo") :: HNil)

然而,对f2的调用没有编译:

could not find implicit value for evidence parameter of type cats.sequence.Sequencer[Option[Int] :: Option[String] :: shapeless.HNil]{type F[X] = Option[X]; type LOut = Int :: String :: shapeless.HNil}

Scala编译似乎在第二种情况下扩展了类型别名Sequencer.Aux,并且无法构造合适的隐式。

如果我直接用扩展类型定义我的函数,那么也不能构造隐式:

def f3[L1 <: HList, L2](xs: L1)(implicit sequencer: Sequencer[L1]{type F[X] = Option[X]; type LOut = L2}) {
println(xs.sequence)
}

除了不能使用更紧凑的上下文绑定语法带来的不便之外,还有两件事我不理解这种情况:

  1. 为什么只有当我使用上下文绑定语法时,隐式证据的类型才会扩展?(这两种语法在语义上有更多的区别吗?(
  2. 为什么Scala不能为扩展的情况构建一个合适的隐式?毕竟,Sequencer.Aux只是一个定义如下的类型别名:
type Aux[L <: HList, F0[_], LOut0] = Sequencer[L] {
type F[X] = F0[X]
type LOut = LOut0
}

我本以为这两种类型的行为完全相同。

看起来像一个bug。应在此处报告Bug:https://github.com/scala/bug/issues

我试图创造一个最小的例子。

也许我过于简化了这个例子,但现在我甚至在HNil的情况下也有问题。

对于

import cats.Applicative
import shapeless.{::, HList, HNil}
import cats.instances.option._
trait Sequencer[L <: HList] extends Serializable {
type F[_]
}
object Sequencer {
type Aux[L <: HList, F0[_]] = Sequencer[L] {
type F[X] = F0[X]
}
implicit def nil[F0[_]](
implicit F: Applicative[F0]
): Aux[HNil, F0] = null
}

implicitly[Sequencer.Aux[HNil, Option]]编译,但implicitly[Sequencer[HNil]{type F[X] = Option[X]}]不编译,并且存在警告(scalacOptions += "-Xlog-implicits"(

//Information: App.this.Sequencer.nil is not a valid implicit value for App.Sequencer[shapeless.HNil]{type F[X] = Option[X]} because:
//hasMatchingSymbol reported error: could not find implicit value for parameter F: cats.Applicative[Option[X]]

也许在这里我们可以看到原因:could not find implicit value for parameter F: cats.Applicative[Option[X]]应该是could not find implicit value for parameter F: cats.Applicative[Option]

但出于某种原因,如果我删除implicit F: Applicative[F0],那么对于

import shapeless.{::, HList, HNil}
trait Sequencer[L <: HList] extends Serializable {
type F[_]
}
object Sequencer {
type Aux[L <: HList, F0[_]] = Sequencer[L] {
type F[X] = F0[X]
}
implicit def nil[F0[_]](): Aux[HNil, F0] = null
}

虽然implicitly[Sequencer.Aux[HNil, Option]](Sequencer.nil())进行了编译,但implicitly[Sequencer.Aux[HNil, Option]]不进行编译。

implicitly[Sequencer[HNil]{type F[X] = Option[X]}]也不编译。如果我们写implicitly[Sequencer[HNil]{type F[X] = Option[X]}](Sequencer.nil()),我们就会明白为什么

//Error: inferred kinds of the type arguments (Option[X]) do not conform to the expected kinds of the type parameters (type F0).
//Option[X]'s type parameters do not match type F0's expected parameters:
//class Option has one type parameter, but type F0 has one

... has one type parameter, but ... has one显示这是一个错误

Bug跟踪器显示"隐式"one_answers"高级"的开放问题

https://github.com/scala/bug/issues?utf8=%E2%9C%93&q=是%3Issue+是%3Open+隐式+高级

最新更新