我有一個關於Scala類型構造器上的類型推理的問題。我跑斯卡拉2.9.1 ...類型構造器的Scala類型推斷
假設我定義的樹:根據我的樹定義
sealed trait Tree[C[_], A]
case class Leaf[C[_], A](a: A) extends Tree[C, A]
case class Node[C[_], A](a: A, c: C[Tree[C, A]]) extends Tree[C, A]
,並定義了二叉樹:
type Pair[A] = (A, A)
type BinaryTree[A] = Tree[Pair, A]
我現在可以定義一個二叉樹整數如下:
val tree: BinaryTree[Int] = Node[Pair, Int](1, (Leaf(2), Leaf(3)))
這個問題是,我必須提供類型參數,只要我在stantiate Node
。
所以,如果做到這一點:
val tree: BinaryTree[Int] = Node(1, (Leaf(2), Leaf(3)))
我得到的錯誤:
error: no type parameters for method apply: (a: A, c: C[Tree[C,A]])Node[C,A] in
object Node exist so that it can be applied to arguments (Int, (Leaf[Pair,Int], Leaf[Pair,Int]))
--- because ---
argument expression's type is not compatible with formal parameter type;
found : (Leaf[Pair,Int], Leaf[Pair,Int])
required: ?C[Tree[?C,?A]]
val tree: BinaryTree[Int] = Node(1, (Leaf(2), Leaf(3)))
^
有沒有什麼辦法可以把該類型檢查器,這樣我就不必明確提供Node
的類型?
謝謝!
修訂didierd的評論
後,如果我理解正確,語句
type Pair[A] = (A, A)
在我原來的問題沒有工作,因爲這對聲明只是語法糖對於Tuple2類型構造函數(它需要兩個類型參數)。這會導致類型推理失敗。
如果我聲明自己的Pair類(如didierd在他的答案中所暗示的那樣),我成功地讓樹正常工作。
// Assume same Tree/Leaf/Node definition given above
case class MyPair[A](_1: A, _2: A)
type BinaryTree[A] = Tree[MyPair, A]
然後,我可以做到這一點...
scala> val t: BinaryTree[Int] = Leaf(3)
t: BinaryTree[Int] = Leaf(3)
scala> val t2: BinaryTree[Int] = Node(1, MyPair(Leaf(2), Leaf(3)))
t2: BinaryTree[Int] = Node(1,MyPair(Leaf(2),Leaf(3)))
我知道didierd提到順便這個解決方案,但這種行爲似乎與我想要的方式。請讓我知道你在想什麼!
關於您的修改代碼:它更類似於@David的解決方案。類型不是完全推斷的,你必須將表達式顯式地鍵入爲BinaryTree [Int]。我認爲這很合理。協變解決方案避免了這種情況,但它帶有一個價格:協方差大多是一件好事,它限制了班級可以做什麼。特別是,它只適用於類型C是協變量。 –