2012-02-08 73 views
7

類型說我有一個較高的kinded型約束更高Kinded在斯卡拉

SuperMap[Key[_],Value[_]]`. 

假設現在我有更具體的,需要對於Key類型參數必須符合爲Value東西;也就是這樣的:

SuperDuperMap[T, Key[T], Value[T]] 

進一步假設我不想只是任何T,而是一個非常具體的一個地方T <: OtherT

SuperDuperPooperMap[T <: OtherT, Key[T], Value[T]] 

可這在斯卡拉做?這通常是一個壞主意嗎?是否有一種等同的方式可以更容易地讀/寫/使用?

回答

11

您的聲明已按預期工作,即您限制的類型爲T以及KeyValue。你寫它的方式,但是,斯卡拉會如果發出類似

scala> class Foo[T <: OtherT, Key[T], Value[T]] 
defined class Foo 

scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]] 
<console>:13: error: Key[SpecialOtherT] takes no type parameters, expected: one 
       new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]] 

,因爲這兩個KeyValue的類型已經由你以前聲明中提到抱怨。因此,這將工作

scala> new Foo[SpecialOtherT, Key, Value] 
res20: Foo[SpecialOtherT,Key,Value] = [email protected] 

這可能不是你想要的。你可以不喜歡這樣

scala> class Foo[T <: OtherT, K <: Key[T], V <: Value[T]] 
defined class Foo 

scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]] 
res21: Foo[SpecialOtherT,Key[SpecialOtherT],Value[SpecialOtherT]] = [email protected] 

在底線,因爲該類型的KeyValueT完全取決於它是有點畫蛇添足與Foo工作時擁有所有的冗餘信息。那麼,爲什麼不使用內部類型聲明,如下所示:

class Foo[T <: OtherT] { 
    type K = Key[T] 
    type V = Value[T] 
} 

然後,你可以訪問類型KV從類中,但不會需要鍵入它每次您創建一個新的答案:

scala> new Foo[SpecialOtherT] 
res23: Foo[SpecialOtherT] = [email protected] 

scala> new Foo[Int] 
<console>:11: error: ... 
+0

謝謝!非常豐富。我對「爲什麼不使用內部類型聲明」的唯一答案是我想要在實例化時推斷K和V的類型。 – duckworthd 2012-02-09 08:37:05

+0

我不確定我是否理解,因爲這個類型實際上是推斷的。根據您的使用情況,您仍然可以使用「外部」中的類型,例如'Foo [T]; class Bar [T] {type Wee = Foo [T]}; def doSomething [T](b:Bar [T])(隱式mf:Manifest [Bar [T] #Wee]){Console println mf}',然後'doSomething(新Bar [雙]]''。同意,這是一個骯髒的例子。 – fotNelton 2012-02-09 09:07:22

3

這可以在Scala中完成嗎?

你是什麼意思?你剛剛做到了!

這是一般的壞主意嗎?

爲什麼會這樣?事實上,這是一個好主意!這是更高級的類型。

有沒有這樣做更容易讀/寫/使用的等效方式?

閱讀 - 對我來說很好。

- 寫/測試/編譯一次,到處使用。

使用 - 編譯器會重建(推斷)「無處不在」類型。

+0

雖然我的代碼編譯,它不能實例化:X – duckworthd 2012-02-09 08:09:39

2

你也許並不需要什麼比一對夫婦類型的別名更爲複雜,

type SuperDuperMap[T, Key[_], Value[_]] = SuperMap[Key, Value] 

type SuperDuperPooperMap[T <: OtherT, Key[_], Value[_]] = SuperMap[Key, Value] 

樣品REPL會話,

scala> new SuperDuperMap[Int, Option, List] {} 
res0: java.lang.Object with SuperDuperMap[Int,Option,List] = ... 

scala> new SuperDuperPooperMap[OtherT, Option, List] {} 
res1: java.lang.Object with SuperDuperPooperMap[OtherT,Option,List] = ...