2015-04-26 64 views
1

我難以使flatUnzip的隱式需求正常工作。目前看起來第一個要求ATuple2[CC1[T1], CC2[T2]]被忽略(因此理智檢查無法編譯)。這裏有什麼建議?在回答時,也請解釋我目前的嘗試有什麼問題。斯卡拉 - 列表元組列表的隱含證據

class MySeq[A](val _seq: Seq[A]) extends AnyVal { 
    def flatUnzip[T1, T2, CC1[T1], CC2[T2]](
     implicit ev1: A =:= Tuple2[CC1[T1], CC2[T2]], 
     ev2: CC1[T1] <:< TraversableOnce[T1], 
     ev3: CC2[T2] <:< TraversableOnce[T2], 
     cbf1: CanBuildFrom[CC1[T1], T1, CC1[T1]], 
     cbf2: CanBuildFrom[CC2[T2], T2, CC2[T2]] 
    ): (CC1[T1], CC2[T2]) = { 
     val foo: Seq[Tuple2[CC1[T1], CC2[T2]]] = _seq // sanity check fails 
     val list1 = cbf1() 
     val list2 = cbf2() 
     for ((xs, ys) <- _seq) { 
     list1 ++= xs 
     list2 ++= ys 
     } 
     return (list1.result, list2.result) 
    } 
    } 

EDIT

我發現了以下工作,但只有當=:=在方向上施加如圖所示:

class MySeq[A](val _seq: Seq[A]) extends AnyVal { 
    def mapBy[B](func: A => B): Map[B, A] = _seq.map(x => (func(x), x)).toMap 
    def flatUnzip[T1, T2, CC1[T1], CC2[T2]](
     implicit 
     ev1: Tuple2[CC1[T1], CC2[T2]] =:= A, 
     ev2: Seq[A] =:= Seq[Tuple2[CC1[T1], CC2[T2]]], 
     ev3: CC1[T1] <:< TraversableOnce[T1], 
     ev4: CC2[T2] <:< TraversableOnce[T2], 
     cbf1: CanBuildFrom[CC1[T1], T1, CC1[T1]], 
     cbf2: CanBuildFrom[CC2[T2], T2, CC2[T2]] 
    ): (CC1[T1], CC2[T2]) = { 
     val list1 = cbf1() 
     val list2 = cbf2() 
     for ((xs, ys) <- _seq: Seq[Tuple2[CC1[T1], CC2[T2]]]) { 
     list1 ++= xs 
     list2 ++= ys 
     } 
     return (list1.result, list2.result) 
    } 
    } 

然而,隨着Seq[Tuple2[CC1[T1], CC2[T2]]] =:= Seq[A]Tuple2[CC1[T1], CC2[T2]] =:= A與替換Seq[A] =:= Seq[Tuple2[CC1[T1], CC2[T2]]]A =:= Tuple2[CC1[T1], CC2[T2]]會導致問題。有人可以解釋爲什麼這裏的訂單很重要,爲什麼需要這些A =:= B關係中的每一個來完成這項工作?

+0

nitpick:這裏不需要'return' –

+0

nitpick#2:'[T1,T2,CC1 [T1],CC2 [T2]]'並不意味着你的想法。你可以只寫'[T1,T2,CC1 [_],CC2 [_]]'。 –

回答

1

您可以通過改變ev1解決它:

implicit ev1: Seq[A] =:= Seq[Tuple2[CC1[T1], CC2[T2]]], 

只是因爲你有證據證明A=:=某種類型,並不意味着證據工程Seq[A]了。所以直接詢問你實際需要的證據。

你還需要到for理解更改爲:

for ((xs, ys) <- _seq: Seq[Tuple2[CC1[T1], CC2[T2]]]) { 

沒有強制轉換觸發搜索,編譯器就不會去尋找ev1

UPDATE:

,正如你在編輯的問題指出,這些修正都不足以使代碼工作。你找到了自己需要的附加修復程序,但它們爲什麼要工作?

這是因爲=:=提供的證據不僅僅是一個被忽略的虛擬值。 =:=延伸Function1,它的功能呢?它從左側的類型轉換爲右側的類型。在運行時,它什麼都不做(它是一個身份函數);但在編譯時,可能需要應用該函數才能將左側的類型轉換爲右側的類型。

在您的修訂代碼中,ev2用於輸入,將_seq轉換爲正確的類型。如果使用-Xprint:typer編譯代碼,您將看到明確的呼叫ev2,ev3ev4

哦,恩,那麼ev1呢?我不確定。這不會在編譯的代碼中顯示出來。我現在沒有看到爲什麼需要它。編譯器似乎需要它作爲墊腳石才能派生出ev2

更新#2:

啊哈!對於ev2,請使用<:<,而不是=:=。那麼你不需要ev1了。

+0

這似乎仍然會導致問題。當我運行它'新的MySeq(列表( (列表(1,2,3),列表(11,12,13)), (列表(4,5,6),列表(14,15,16 )), (List(7,8,9),List(17,18,19)) ))。flatUnzip'它說'不能證明Seq [(List [Int],List [Int])] = := Seq [(CC1 [T1],CC2 [T2])]' – Kvass

+0

爲什麼'ev1'需要在輸出端使用?輸出的類型是'(CC1 [T1],CC2 [T2])',它沒有被定義爲w.r.t. 'A' – Kvass

+0

嗯,你是對的。我不知道爲什麼需要'ev1'。 '-Xprint:typer'不會提供任何線索。我已經適當地編輯了我的答案。 –