2011-08-26 65 views
7

我在使用Haskell的類型系統時出現問題。我確定我的問題很常見,但我不知道如何描述它,除非是針對我的程序。使用Haskell的類型系統實現正確的抽象

我試圖代表的概念是:

  • 數據點,其中每一個取若干形式中的一個,例如(id,病例數量,控件數量),(id,病例數量,人口數量)

  • 集合數據點和集合信息:(一組id,總個案,總控件)除去點(所以每個品種點,都有一個對應的各種組)

我能有一類點類型,並確定每個品種的點作爲自己的類型。或者,我可以爲每個品種提供一個點類型和一個不同的數據構造函數。類似的點集。

我有每種方法至少一個擔憂:

  • 隨着類型類:避免函數名稱衝突將是煩人。例如,這兩種類型的點都可以使用一個函數來提取「個案數量」,但是類型類不能要求使用該函數,因爲其他點類型可能沒有案例。如果沒有類型類:我寧願不導出Point模塊(提供其他更安全的函數來創建新值)的數據構造函數。如果沒有數據構造函數,我將無法確定給定Point值的種類。

什麼樣的設計可能有助於減少這些(和其他)問題?

+0

在你需要同樣對待你的數據點在什麼情況?你說每個表單都需要自己的各種集合,而像「案例數量」這樣的操作並不普遍。 –

回答

4

爲了擴展sclv的答案,有一個緊密相關的概念的擴展家族,相當於提供解構一個值的一些手段:Catamorphisms,這是廣義摺疊;教會編碼通過其操作代表數據,通常相當於部分將變形性應用於其解構的價值; CPS變換,其中教會編碼類似於對每種情況分別延續的具體化模式匹配;將數據表示爲使用它的操作的集合,通常稱爲面向對象編程;等等。

在你的情況,你似乎想什麼是一個抽象類型,即一個不出口的內部形式,但不是完全密封的一個,即離開開表示,以功能模塊中定義它。這與Data.Map.Map之類的模式相同。你可能不要想要去類型類路由,因爲它聽起來像你需要使用各種數據點,而不是任意選擇一種類型的數據點。

最有可能的是,從模塊中導出的「智能構造函數」創建值的一些組合以及從模塊導出的各種解構函數(如上所述)是最好的起點。從那裏開始,我預計剩下的大部分細節應該有一個明顯的方法來接下來。

3

隨着後者的解決方案(無類型類),你可以在類型,而不是構造函數導出catamorphism ..

data MyData = PointData Double Double | ControlData Double Double Double | SomeOtherData String Double 

foldMyData pf cf sf d = case d of 
     (PointData x y) -> pf x y 
     (ControlData x y z) -> cf x y z 
     (SomeOtherData s x) -> sf s x 

你有辦法拉開你的數據到任何你想要這樣, (包括只是忽略返回使用的構造函數類型的值和傳遞函數),而不提供構造數據的一般方法。

2

只要不打算在單個數據結構中混合不同的數據點,我發現基於類型的方法會更好。

你提到的名稱衝突問題可以通過爲每個不同的領域創建一個單獨的類型類來解決,就像這樣:

class WithCases p where 
    cases :: p -> NumberOfCases