简体   繁体   English

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

[英]Scala Kittens: implicit Sequencer value doesn't seem to work with context bound syntax

In my understanding the following two functions and their calls should be identical:据我了解,以下两个函数及其调用应该是相同的:

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)

However, the call to f2 doesn't compile:但是,对 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}

The Scala compile seems to expand the type alias Sequencer.Aux in the second case and isn't able to construct a suitable implicit. Scala 编译似乎在第二种情况下扩展了类型别名 Sequencer.Aux 并且无法构造合适的隐式。

If I directly define my function with the expanded type, no implicit can be constructed either:如果我直接用扩展类型定义我的 function ,也不能构造隐式:

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

Apart from the inconvenience of not being able to use the more compact context bound syntax there are two things that I don't understand about this situation:除了无法使用更紧凑的上下文绑定语法带来的不便外,我对这种情况还有两件事不明白:

  1. why is the type of the evidence implicit only expanded if i use the context bound syntax?为什么只有在我使用上下文绑定语法时才会扩展隐含的证据类型? (and are there more semantical differences between the two syntaxes?) (两种语法之间是否存在更多语义差异?)
  2. why is Scala unable to construct a suitable implicit for the expanded case?为什么 Scala 无法为扩展案例构造合适的隐式? After all, Sequencer.Aux is only a type alias defined like this:毕竟,Sequencer.Aux 只是这样定义的类型别名:
type Aux[L <: HList, F0[_], LOut0] = Sequencer[L] {
  type F[X] = F0[X]
  type LOut = LOut0
}

I would have expected both types to behave identical.我本来希望这两种类型的行为相同。

Looks like a bug.看起来像一个错误。 Bugs should be reported here: https://github.com/scala/bug/issues应在此处报告错误: https://github.com/scala/bug/issues

I tried to create minimal example.我试图创建最小的例子。

And maybe I oversimplified the example but now I have issues even with HNil case. 也许我过度简化了这个例子,但现在即使是 HNil案例我也遇到了问题。

For为了

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]] compiles but implicitly[Sequencer[HNil]{type F[X] = Option[X]}] doesn't and there is warning ( scalacOptions += "-Xlog-implicits" ) 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]]

And probably here we can see the reason: could not find implicit value for parameter F: cats.Applicative[Option[X]] should be could not find implicit value for parameter F: cats.Applicative[Option] .可能在这里我们可以看到原因: could not find implicit value for parameter F: cats.Applicative[Option[X]]应该could not find implicit value for parameter F: cats.Applicative[Option]

But for some reason if I remove implicit F: Applicative[F0] then for但是由于某种原因,如果我删除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]] doesn't compile although implicitly[Sequencer.Aux[HNil, Option]](Sequencer.nil()) compiles.尽管implicitly[Sequencer.Aux[HNil, Option]](Sequencer.nil())编译,但隐式implicitly[Sequencer.Aux[HNil, Option]]不会编译。

implicitly[Sequencer[HNil]{type F[X] = Option[X]}] doesn't compile either. implicitly[Sequencer[HNil]{type F[X] = Option[X]}]也不编译。 And if we write implicitly[Sequencer[HNil]{type F[X] = Option[X]}](Sequencer.nil()) we'll see why如果我们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 shows that this is a bug. ... has one type parameter, but... has one表明这是一个错误。

Bug tracker shows open issues for "implicit" and "higher-kind"错误跟踪器显示“隐式”和“高级”的未解决问题

https://github.com/scala/bug/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+implicit+higher-kind https://github.com/scala/bug/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+implicit+higher-kind

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM