problem with implicit ambiguity between my method and conforms in Predef
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.collectio开发者_如何学编程ns.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)
}
}
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 of Function1
(says Function2
but i guess that is a mistake). But since <:<
is a subclass of Function1
it can be passed in whenever Function1
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 type A => A
, it is sufficient to have an implicit value of A
in scope.
In your case the implicit def hParseNil: HNil => HNil
has the same priority as conforms
and thus both could be equally applied.
I see two possible solutions:
- just remove the
hParseNil
, i think your code still works. shadow the
Predef
'sconforms
by naming yours the same:implicit def conforms: HNil => HNil = _ => new 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
精彩评论