我的方法和 Predef 中的一致性之间存在隐含歧义的问题
以下代码,摘自Apocalisp的优秀博客系列: scala 中的类型级编程 ,并修改对于隐式解析场景。但是,这不会编译,并显示以下消息:
error: ambiguous implicit values:
both method hParseNil in object HApplyOps of type => (com.mystuff.bigdata.commons.collections.hlist.HNil) => com.mystuff.bigdata.commons.collections.hlist.HNil
and method conforms in object Predef of type [A]<:<[A,A]
match expected type (com.mystuff.bigdata.commons.collections.hlist.HNil) => com.amadesa.bigdata.commons.collections.hlist.HNil
val l = hparse[HNil,HNil](HNil)
有人可以解释为什么会发生这种情况,以及它是否可以修复吗?
sealed trait HList
final case class HCons[H, T <: HList](head: H, tail: T) extends HList {
def :+:[T](v: T) = HCons(v, this)
}
sealed class HNil extends HList {
def :+:[T](v: T) = HCons(v, this)
}
object HNil extends HNil
// aliases for building HList types and for pattern matching
object HList {
type :+:[H, T <: HList] = HCons[H, T]
val :+: = HCons
}
object HApplyOps
{
import HList.:+:
implicit def hParseNil: HNil => HNil = _ => HNil
implicit def hParseCons[InH,OutH,TIn <:HList,TOut<:HList](implicit parse:InH=>OutH,parseTail:TIn=>TOut): (InH :+: TIn) => (OutH :+: TOut) =
in => HCons(parse(in.head),parseTail(in.tail))
def hparse[In <: HList, Out <: HList](in:In)(implicit parse: In => Out):Out = in
}
object PG {
import HList._
def main(args: Array[String]) {
import HApplyOps._
val l = hparse[HNil,HNil](HNil)
}
}
The following code, which is taken from Apocalisp's excellent blog series:
Type level programming in scala , and modified for an implicit parsing scenario. However, this does not compile, with the following message:
error: ambiguous implicit values:
both method hParseNil in object HApplyOps of type => (com.mystuff.bigdata.commons.collections.hlist.HNil) => com.mystuff.bigdata.commons.collections.hlist.HNil
and method conforms in object Predef of type [A]<:<[A,A]
match expected type (com.mystuff.bigdata.commons.collections.hlist.HNil) => com.amadesa.bigdata.commons.collections.hlist.HNil
val l = hparse[HNil,HNil](HNil)
Can someone please explain why this happens, and if it's fixable?
sealed trait HList
final case class HCons[H, T <: HList](head: H, tail: T) extends HList {
def :+:[T](v: T) = HCons(v, this)
}
sealed class HNil extends HList {
def :+:[T](v: T) = HCons(v, this)
}
object HNil extends HNil
// aliases for building HList types and for pattern matching
object HList {
type :+:[H, T <: HList] = HCons[H, T]
val :+: = HCons
}
object HApplyOps
{
import HList.:+:
implicit def hParseNil: HNil => HNil = _ => HNil
implicit def hParseCons[InH,OutH,TIn <:HList,TOut<:HList](implicit parse:InH=>OutH,parseTail:TIn=>TOut): (InH :+: TIn) => (OutH :+: TOut) =
in => HCons(parse(in.head),parseTail(in.tail))
def hparse[In <: HList, Out <: HList](in:In)(implicit parse: In => Out):Out = in
}
object PG {
import HList._
def main(args: Array[String]) {
import HApplyOps._
val l = hparse[HNil,HNil](HNil)
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
虽然我无法准确告诉您
Predef.conforms
的目的,但我可以告诉您歧义错误似乎是正确的(不幸的是)。在源代码的评论中,它甚至说<:<
是由于Function1
的歧义问题而引入的(说Function2
但我猜这是一个错误)。但由于<:<
是Function1
的子类,因此只要需要Function1
就可以传入它,因此在您的情况下可以将<:<
传递给 hparse。现在隐式 def 符合 [A]: A <:< A 的效果(根据我的理解),每当一个方法需要类型
A =>; A
,作用域内有一个隐式值A
就足够了。在您的情况下,隐式 def hParseNil: HNil => HNil 与
conforms
具有相同的优先级,因此两者可以同等应用。我看到两种可能的解决方案:
hParseNil
,我认为您的代码仍然有效。通过命名相同的名称来隐藏
Predef
的conforms
:隐式 def 符合:HNil => HNil=_=> new HNil
Although i can't tell you exactly the purpose of
Predef.conforms
, i can tell you the ambiguity error seems correct (unfortunately). In the comment in the source it even says that<:<
was introduced because of ambiguity problems ofFunction1
(saysFunction2
but i guess that is a mistake). But since<:<
is a subclass ofFunction1
it can be passed in wheneverFunction1
is expected, so in your case its possible to pass in<:<
to hparse.Now the
implicit def conforms[A]: A <:< A
has the effect (from what i understand) that whenever a method expects a typeA => A
, it is sufficient to have an implicit value ofA
in scope.In your case the
implicit def hParseNil: HNil => HNil
has the same priority asconforms
and thus both could be equally applied.I see two possible solutions:
hParseNil
, i think your code still works.shadow the
Predef
'sconforms
by naming yours the same:implicit def conforms: HNil => HNil = _ => new HNil
您只需将函数文字
hParseNil
替换为普通函数即可。implicit def hParseNil(a:HNil): HNil = HNil
而不是
implicit def hParseNil: HNil => HNil=_=> HNil
You can just replace the function literal
hParseNil
to a normal function.implicit def hParseNil(a:HNil): HNil = HNil
instead of
implicit def hParseNil: HNil => HNil = _ => HNil