给出一些方法
def f[A,B](p: A)(implicit a: X[A,B], b: Y[B])
隐式参数列表中a
之前的b
顺序对类型推断是否重要?
我认为只有参数在不同参数列表中的位置很重要,例如类型信息仅从左到右通过参数列表流动。
我问,因为我注意到在单隐式列表中更改隐式参数的顺序使我的程序编译。
以下代码正在使用:
这是一个简单的sbt构建文件,可以帮助编译示例:
scalaVersion := "2.11.5"
libraryDependencies += "com.chuusai" %% "shapeless" % "2.1.0"
scalaSource in Compile := baseDirectory.value
在示例上。此代码编译:
import shapeless._
import shapeless.ops.hlist.Comapped
class Foo {
trait NN
trait Node[X] extends NN
object Computation {
def foo[LN <: HList, N <: HList, TupN <: Product, FunDT]
(dependencies: TupN)
(computation: FunDT)
(implicit tupToHlist: Generic.Aux[TupN, LN], unwrap: Comapped.Aux[LN, Node, N]) = ???
// (implicit unwrap: Comapped.Aux[LN, Node, N], tupToHlist: Generic.Aux[TupN, LN]) = ???
val ni: Node[Int] = ???
val ns: Node[String] = ???
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
}
}
并且此代码失败
import shapeless._
import shapeless.ops.hlist.Comapped
class Foo {
trait NN
trait Node[X] extends NN
object Computation {
def foo[LN <: HList, N <: HList, TupN <: Product, FunDT]
(dependencies: TupN)
(computation: FunDT)
// (implicit tupToHlist: Generic.Aux[TupN, LN], unwrap: Comapped.Aux[LN, Node, N]) = ???
(implicit unwrap: Comapped.Aux[LN, Node, N], tupToHlist: Generic.Aux[TupN, LN]) = ???
val ni: Node[Int] = ???
val ns: Node[String] = ???
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
}
}
出现以下编译错误
Error:(22, 25) ambiguous implicit values:
both method hnilComapped in object Comapped of type [F[_]]=> shapeless.ops.hlist.Comapped.Aux[shapeless.HNil,F,shapeless.HNil]
and method hlistComapped in object Comapped of type [H, T <: shapeless.HList, F[_]](implicit mt: shapeless.ops.hlist.Comapped[T,F])shapeless.ops.hlist.Comapped.Aux[shapeless.::[F[H],T],F,shapeless.::[H,mt.Out]]
match expected type shapeless.ops.hlist.Comapped.Aux[LN,Foo.this.Node,N]
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
^
Error:(22, 25) could not find implicit value for parameter unwrap: shapeless.ops.hlist.Comapped.Aux[LN,Foo.this.Node,N]
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
^
Error:(22, 25) not enough arguments for method foo: (implicit unwrap: shapeless.ops.hlist.Comapped.Aux[LN,Foo.this.Node,N], implicit tupToHlist: shapeless.Generic.Aux[(Foo.this.Node[Int], Foo.this.Node[String]),LN])Nothing.
Unspecified value parameters unwrap, tupToHlist.
val x = foo((ni,ns))((i: Int, s: String) => s + i.toString)
^
答案 0 :(得分:2)
通常没关系。如果您查看language spec,则不会提及依赖于参数顺序的分辨率。
我查看了无形的源代码,我无法想出为什么会出现这种错误。
快速搜索语言的错误回购,我发现similar issue显然已经解决了。但它没有说明修复是否涉及处理症状(使上下文边界不破坏编译)或原因(对隐式参数排序的限制。)
因此,我认为这是一个编译器错误,它与第3点中链接的问题紧密相关。
此外,如果您能找到比我自己更严格的分析产生的第二意见,我建议您提交错误报告:)
希望这会让你的思绪得到安息。干杯!
答案 1 :(得分:1)
根据我对Lorand Szakacs提到的the issue的评论的解读,我得出的结论是隐式参数的顺序在Scala编译器的当前版本2.11
中很重要。
这是因为参与讨论的开发人员似乎认为订单很重要;他们没有明确说明。
我不知道有关此主题的语言规范。
答案 2 :(得分:0)
重新排序它们只会破坏显式传递它们的代码,以及所有已编译的代码。其他一切都不会受到影响。