2015-03-19 47 views
5

考慮一些方法在Scala中,隱式參數的順序是否重要?

def f[A,B](p: A)(implicit a: X[A,B], b: Y[B]) 

是否的ab之前類型推斷隱含參數列表之內的順序?

我認爲只有參數在不同參數列表中的位置很重要,例如,類型信息只能通過參數列表從左到右流動。

我在問,因爲我注意到,改變單隱式列表中的隱式參數的順序使得我的編譯程序成爲可能。

真實的例子

下面的代碼是使用:

  • 不成形2.1.0
  • 斯卡拉2.11.5

下面是一個簡單的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

順序應該不重要,至少是孤立的。然而,改變隱式的順序肯定會改變方法的簽名,所以它會改變它所定義的類/特徵的類型。在任何wase中,你都應該發佈一段代碼片斷,以顯示改變順序如何改變編譯結果,否則很難討論這個問題。 – 2015-03-19 09:02:28

+0

@RégisJean-Gilles我添加了一個有點小的例子。 – ziggystar 2015-03-19 12:55:35

回答

1

根據我讀到的Lorand Szakacs提到的the issue的評論,我得出的結論是隱含參數的順序在當前版本的Scala編譯器的2.11中很重要。

這是因爲參與討論的開發者似乎認爲訂單很重要;他們沒有明確說明。

我不知道提及此主題的任何語言規範。

0

重新排列它們只會打破,明確傳遞它們的代碼,以及所有編譯碼。其他一切都不會受到影響。

+0

請看我的例子。 – ziggystar 2015-03-19 12:55:14

2
  1. 通常它應該沒有關係。如果你看看language spec它沒有提到分辨率依賴於參數順序。

  2. 我看了無形的源代碼,我無法想出這個錯誤會出現的原因。

  3. 並通過語言錯誤回購進行快速搜索,我發現一個顯然已解決的similar issue。但是,如果修訂涉及治標(使上下文範圍不破編譯),或因爲它沒有說明(隱參數排序的限制。)

所以我認爲這是一個編譯器錯誤,並它是緊密相關的掛點3

同樣的問題,我建議你提交錯誤報告,如果你能找到的起因是更嚴格的分析比我自己:)

希望第二意見這讓你的大腦休息。乾杯!

+2

我已經閱讀了關於該問題的評論,並且似乎所有評論者隱含地認爲隱含參數的順序很重要。 – ziggystar 2015-03-19 16:45:52