Hello: I recently studied Scala (my kindred background was mostly in C ++ templates), and I came across the fact that I don’t understand about Scala right now, and it drives me crazy. :(
(Also, this is my first post on StackOverflow where I noticed that most of the really amazing Scala people seem to hang out, so I'm sorry if I do something terribly stupid with this mechanism.)
My specific confusion is related to implicit argument binding: I came up with a specific case where an implicit argument refuses to bind, but a function with seemingly identical semantics does.
Now this, of course, may be a compiler error, but, given that I just started working with Scala, the probability that I have already encountered some serious error is small enough that I expect someone to explain that I did wrong .; R
I looked at the code and slightly reduced it to come up with one example that does not work. Unfortunately, this example is still quite complicated, since the problem seems to arise only in generalization :(
1) simplified code that does not work as I expected
import HList.::
trait HApplyOps {
implicit def runNil
(input :HNil)
(context :Object)
:HNil
= {
HNil()
}
implicit def runAll[Input <:HList, Output <:HList]
(input :Int::Input)
(context :Object)
(implicit run :Input=>Object=>Output)
:Int::Output
= {
HCons(0, run(input.tail)(context))
}
def runAny[Input <:HList, Output <:HList]
(input :Input)
(context :Object)
(implicit run :Input=>Object=>Output)
:Output
= {
run(input)(context)
}
}
sealed trait HList
final case class HCons[Head, Tail <:HList]
(head :Head, tail :Tail)
extends HList
{
def ::[Value](value :Value) = HCons(value, this)
}
final case class HNil()
extends HList
{
def ::[Value](value :Value) = HCons(value, this)
}
object HList extends HApplyOps {
type ::[Head, Tail <:HList] = HCons[Head, Tail]
}
class Test {
def main(args :Array[String]) {
HList.runAny( HNil())(null)
HList.runAny(0::HNil())(null)
}
}
This code compiled with Scala 2.9.0.1 returns the following error:
broken1.scala:53: error: No implicit view available from HCons[Int,HNil] => (java.lang.Object) => Output.
HList.runAny(0::HNil())(null)
My expectation in this case is that it runAllwill be tied to an implicit argument runto runAny.
, runAll , , , , , , (, , ), :
2) ,
implicit def runAll[Input <:HList, Output <:HList]
(implicit run :Input=>Object=>Output)
:Int::Input=>Object=>Int::Output
= {
input =>
context =>
HCons(0, run(input.tail)(context))
}
, : ?; ( , :
1: [Input <:HList, Output <:HList] (Int::Input)(Object):Int::Output
2: [Input <:Hlist, Output <:HList] :Int::Input=>Object=>Int::Output
, "" ( , , ):
3) runAll Output HNil
implicit def runAll[Input <:HList, Output <:HList]
(input :Int::Input)
(context :Object)
(implicit run :Input=>Object=>HNil)
:Int::HNil
= {
HCons(0, run(input.tail)(context))
}
4)
trait HApplyOps {
implicit def runNil
(input :HNil)
:HNil
= {
HNil()
}
implicit def runAll[Input <:HList, Output <:HList]
(input :Int::Input)
(implicit run :Input=>Output)
:Int::Output
= {
HCons(0, run(input.tail))
}
def runAny[Input <:HList, Output <:HList]
(input :Input)
(context :Object)
(implicit run :Input=>Output)
:Output
= {
run(input)
}
}
, , .: (
( , , , , : runAny , "implicit def implicit" .)