2012-02-12 51 views
7

我可以在Scala中使用哪些技術來處理長型參數列表?Scala:如何使用長型參數列表

我正在研究一個小框架,用於運行具有不同模擬環境的各種類型的遊戲。我試圖保持框架的某些部分相對通用,所以我介紹了各種類型作爲類型參數,例如環境狀態,遊戲結果等。

這一切在功能上都很好,我也是獲得類型安全但通用的框架所需的好處。但是類型簽名已經發展到使得代碼難以閱讀並且重構它變得相當麻煩的程度。頂級模擬器的簽名有八個類型參數,許多主要類型有三到五個。個別的編譯器類型錯誤,因爲它們列出了類或函數參數的類型(當然這也是類型參數化的)似乎經常運行到一百行。

有時,但很少,我可以省略類型參數,例如,在構造函數上。但在大多數情況下,至少有一種類型不會被推斷,所以我最終不得不插入整個類型簽名。

顯然這並不理想,我正在尋找方法來解決這個問題。任何意見,將不勝感激!

+6

的樣品幾行代碼總是理解;) – agilesteel 2012-02-12 07:19:47

+0

這是一個非常普遍的問題。我不確定示例代碼會增加很多價值。它只是通常的事情:特徵,類,函數,每個都有類型參數,字段/成員也有類型參數。 – 2012-02-12 08:53:17

回答

8

考慮這種情況,當你有一組密切相關的類型參數;你將它們作爲類型參數傳遞給它們。在這個例子中,這個組是AB

trait X[A, B, C] { 
    new Y[A, B, Int] {} 
} 

trait Y[A, B, D] { 
    def a: A = sys.error("") 
} 

可以打包這兩種類型與含類型別名類型成員的單一類型參數:

type AB = { type A; type B } 
trait Y[ab <: AB, D] { 
    def a: ab#A = sys.error("") 
} 
trait X[ab <: AB, C] { 
    new Y[ab, C] {} 
} 
new X[{ type A=Int; type B=Int}, String] {} 
+0

哦,那很整齊!我會盡快嘗試! – 2012-02-12 18:07:09

+0

您還保留使用此方法的差異的能力。 – retronym 2012-02-12 18:19:48

+1

如何指定方差?在你的例子中,例如如果Y最初是特質Y [+ A,-B]? – 2012-02-13 04:53:10

10

想到兩個解決方案。

  1. 使用類型別名。

    scala> class Foo[A, B, C, D, E] 
    defined class Foo 
    
    scala> type Bar[A] = Foo[A, Int, Int, Int, Float] 
    defined type alias Bar 
    
    scala> new Bar[String] 
    res23: Foo[String,Int,Int,Int,Float] = [email protected] 
    
  2. 使用abstract type members而不是類型參數。

    scala> class Bar { 
        | type A 
        | type B <: AnyVal 
        | type C 
        | } 
    defined class Bar 
    
    scala> new Bar { 
        | type A = String 
        | type B = Int 
        | type C = Int 
        | } 
    res24: Bar{type A = String; type B = Int; type C = Int} = [email protected] 
    
    scala> trait Baz { 
        | type A = String 
        | } 
    defined trait Baz 
    
    scala> new Bar with Baz { 
        | type B = Int 
        | type C = String 
        | } 
    res25: Bar with Baz{type B = Int; type C = String} = [email protected] 
    
    scala> null.asInstanceOf[res25.A] 
    res26: res25.A = null 
    
    scala> implicitly[res25.A =:= String] 
    res27: =:=[res25.A,String] = <function1> 
    

你可能想分享一些代碼,使我們,使我們可以提供一些更具體的建議。

+0

我已經使用的第一個答案;如果以某種方式使用定義的類型別名來訪問底層類型的構造函數,它會更好。第二個是有趣的;我會探討這一點。 – 2012-02-12 08:55:55